Merge PR #3517: Increasing test coverage in keys/client package
This commit is contained in:
parent
cff985ffc5
commit
b5fdb83830
|
@ -204,7 +204,7 @@ jobs:
|
||||||
export VERSION="$(git describe --tags --long | sed 's/v\(.*\)/\1/')"
|
export VERSION="$(git describe --tags --long | sed 's/v\(.*\)/\1/')"
|
||||||
for pkg in $(go list ./... | grep -v github.com/cosmos/cosmos-sdk/cmd/gaia/cli_test | grep -v '/simulation' | circleci tests split --split-by=timings); do
|
for pkg in $(go list ./... | grep -v github.com/cosmos/cosmos-sdk/cmd/gaia/cli_test | grep -v '/simulation' | circleci tests split --split-by=timings); do
|
||||||
id=$(echo "$pkg" | sed 's|[/.]|_|g')
|
id=$(echo "$pkg" | sed 's|[/.]|_|g')
|
||||||
GOCACHE=off go test -timeout 8m -race -coverprofile=/tmp/workspace/profiles/$id.out -covermode=atomic "$pkg" | tee "/tmp/logs/$id-$RANDOM.log"
|
GOCACHE=off go test -timeout 8m -race -coverprofile=/tmp/workspace/profiles/$id.out -covermode=atomic -tags='ledger test_ledger_mock' "$pkg" | tee "/tmp/logs/$id-$RANDOM.log"
|
||||||
done
|
done
|
||||||
- persist_to_workspace:
|
- persist_to_workspace:
|
||||||
root: /tmp/workspace
|
root: /tmp/workspace
|
||||||
|
|
7
Makefile
7
Makefile
|
@ -145,10 +145,13 @@ test_cli:
|
||||||
@go test -p 4 `go list github.com/cosmos/cosmos-sdk/cmd/gaia/cli_test` -tags=cli_test
|
@go test -p 4 `go list github.com/cosmos/cosmos-sdk/cmd/gaia/cli_test` -tags=cli_test
|
||||||
|
|
||||||
test_ledger:
|
test_ledger:
|
||||||
@go test `go list github.com/cosmos/cosmos-sdk/crypto` -tags='cgo ledger test_real_ledger'
|
# First test with mock
|
||||||
|
@go test `go list github.com/cosmos/cosmos-sdk/crypto` -tags='cgo ledger test_ledger_mock'
|
||||||
|
# Now test with a real device
|
||||||
|
@go test -v `go list github.com/cosmos/cosmos-sdk/crypto` -tags='cgo ledger'
|
||||||
|
|
||||||
test_unit:
|
test_unit:
|
||||||
@VERSION=$(VERSION) go test $(PACKAGES_NOSIMULATION)
|
@VERSION=$(VERSION) go test $(PACKAGES_NOSIMULATION) -tags='test_ledger_mock'
|
||||||
|
|
||||||
test_race:
|
test_race:
|
||||||
@VERSION=$(VERSION) go test -race $(PACKAGES_NOSIMULATION)
|
@VERSION=$(VERSION) go test -race $(PACKAGES_NOSIMULATION)
|
||||||
|
|
|
@ -77,6 +77,7 @@ IMPROVEMENTS
|
||||||
* [\#3497](https://github.com/cosmos/cosmos-sdk/issues/3497) `gaiad gentx` supports `--ip` and `--node-id` flags to override defaults.
|
* [\#3497](https://github.com/cosmos/cosmos-sdk/issues/3497) `gaiad gentx` supports `--ip` and `--node-id` flags to override defaults.
|
||||||
* [\#3518](https://github.com/cosmos/cosmos-sdk/issues/3518) Fix flow in
|
* [\#3518](https://github.com/cosmos/cosmos-sdk/issues/3518) Fix flow in
|
||||||
`keys add` to show the mnemonic by default.
|
`keys add` to show the mnemonic by default.
|
||||||
|
* [\#3517](https://github.com/cosmos/cosmos-sdk/pull/3517) Increased test coverage
|
||||||
|
|
||||||
* Gaia
|
* Gaia
|
||||||
* [\#3418](https://github.com/cosmos/cosmos-sdk/issues/3418) Add vesting account
|
* [\#3418](https://github.com/cosmos/cosmos-sdk/issues/3418) Add vesting account
|
||||||
|
|
|
@ -770,7 +770,7 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk
|
||||||
)
|
)
|
||||||
|
|
||||||
if ctx.BlockGasMeter().GasConsumed() < startingGas {
|
if ctx.BlockGasMeter().GasConsumed() < startingGas {
|
||||||
panic(sdk.ErrorGasOverflow{"tx gas summation"})
|
panic(sdk.ErrorGasOverflow{Descriptor: "tx gas summation"})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
|
@ -15,10 +15,26 @@ import (
|
||||||
// MinPassLength is the minimum acceptable password length
|
// MinPassLength is the minimum acceptable password length
|
||||||
const MinPassLength = 8
|
const MinPassLength = 8
|
||||||
|
|
||||||
|
var currentStdin *bufio.Reader
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
currentStdin = bufio.NewReader(os.Stdin)
|
||||||
|
}
|
||||||
|
|
||||||
// BufferStdin is used to allow reading prompts for stdin
|
// BufferStdin is used to allow reading prompts for stdin
|
||||||
// multiple times, when we read from non-tty
|
// multiple times, when we read from non-tty
|
||||||
func BufferStdin() *bufio.Reader {
|
func BufferStdin() *bufio.Reader {
|
||||||
return bufio.NewReader(os.Stdin)
|
return currentStdin
|
||||||
|
}
|
||||||
|
|
||||||
|
// OverrideStdin allows to temporarily override stdin
|
||||||
|
func OverrideStdin(newStdin *bufio.Reader) (cleanUp func()) {
|
||||||
|
prevStdin := currentStdin
|
||||||
|
currentStdin = newStdin
|
||||||
|
cleanUp = func() {
|
||||||
|
currentStdin = prevStdin
|
||||||
|
}
|
||||||
|
return cleanUp
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPassword will prompt for a password one-time (to sign a tx)
|
// GetPassword will prompt for a password one-time (to sign a tx)
|
||||||
|
|
|
@ -90,7 +90,7 @@ input
|
||||||
output
|
output
|
||||||
- armor encrypted private key (saved to file)
|
- armor encrypted private key (saved to file)
|
||||||
*/
|
*/
|
||||||
func runAddCmd(cmd *cobra.Command, args []string) error {
|
func runAddCmd(_ *cobra.Command, args []string) error {
|
||||||
var kb keys.Keybase
|
var kb keys.Keybase
|
||||||
var err error
|
var err error
|
||||||
var encryptPassword string
|
var encryptPassword string
|
||||||
|
@ -265,7 +265,7 @@ func printCreate(info keys.Info, showMnemonic bool, mnemonic string) error {
|
||||||
output := viper.Get(cli.OutputFlag)
|
output := viper.Get(cli.OutputFlag)
|
||||||
|
|
||||||
switch output {
|
switch output {
|
||||||
case "text":
|
case OutputFormatText:
|
||||||
fmt.Fprintln(os.Stderr)
|
fmt.Fprintln(os.Stderr)
|
||||||
printKeyInfo(info, Bech32KeyOutput)
|
printKeyInfo(info, Bech32KeyOutput)
|
||||||
|
|
||||||
|
@ -276,7 +276,7 @@ func printCreate(info keys.Info, showMnemonic bool, mnemonic string) error {
|
||||||
fmt.Fprintln(os.Stderr, "")
|
fmt.Fprintln(os.Stderr, "")
|
||||||
fmt.Fprintln(os.Stderr, mnemonic)
|
fmt.Fprintln(os.Stderr, mnemonic)
|
||||||
}
|
}
|
||||||
case "json":
|
case OutputFormatJSON:
|
||||||
out, err := Bech32KeyOutput(info)
|
out, err := Bech32KeyOutput(info)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
package keys
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
"github.com/tendermint/tendermint/libs/cli"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/tests"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/client"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_runAddCmdBasic(t *testing.T) {
|
||||||
|
cmd := addKeyCommand()
|
||||||
|
assert.NotNil(t, cmd)
|
||||||
|
|
||||||
|
// Missing input (enter password)
|
||||||
|
err := runAddCmd(cmd, []string{"keyname"})
|
||||||
|
assert.EqualError(t, err, "EOF")
|
||||||
|
|
||||||
|
// Prepare a keybase
|
||||||
|
kbHome, kbCleanUp, err := tests.GetTempDir("Test_runDeleteCmd")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotNil(t, kbHome)
|
||||||
|
defer kbCleanUp()
|
||||||
|
viper.Set(cli.HomeFlag, kbHome)
|
||||||
|
|
||||||
|
/// Test Text
|
||||||
|
viper.Set(cli.OutputFlag, OutputFormatText)
|
||||||
|
// Now enter password
|
||||||
|
cleanUp1 := client.OverrideStdin(bufio.NewReader(strings.NewReader("test1234\ntest1234\n")))
|
||||||
|
defer cleanUp1()
|
||||||
|
err = runAddCmd(cmd, []string{"keyname1"})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
/// Test Text - Replace? >> FAIL
|
||||||
|
viper.Set(cli.OutputFlag, OutputFormatText)
|
||||||
|
// Now enter password
|
||||||
|
cleanUp2 := client.OverrideStdin(bufio.NewReader(strings.NewReader("test1234\ntest1234\n")))
|
||||||
|
defer cleanUp2()
|
||||||
|
err = runAddCmd(cmd, []string{"keyname1"})
|
||||||
|
assert.Error(t, err)
|
||||||
|
|
||||||
|
/// Test Text - Replace? Answer >> PASS
|
||||||
|
viper.Set(cli.OutputFlag, OutputFormatText)
|
||||||
|
// Now enter password
|
||||||
|
cleanUp3 := client.OverrideStdin(bufio.NewReader(strings.NewReader("y\ntest1234\ntest1234\n")))
|
||||||
|
defer cleanUp3()
|
||||||
|
err = runAddCmd(cmd, []string{"keyname1"})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
// Check JSON
|
||||||
|
viper.Set(cli.OutputFlag, OutputFormatJSON)
|
||||||
|
// Now enter password
|
||||||
|
cleanUp4 := client.OverrideStdin(bufio.NewReader(strings.NewReader("test1234\ntest1234\n")))
|
||||||
|
defer cleanUp4()
|
||||||
|
err = runAddCmd(cmd, []string{"keyname2"})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
type MockResponseWriter struct {
|
||||||
|
dataHeaderStatus int
|
||||||
|
dataBody []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (MockResponseWriter) Header() http.Header {
|
||||||
|
panic("Unexpected call!")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *MockResponseWriter) Write(data []byte) (int, error) {
|
||||||
|
w.dataBody = append(w.dataBody, data...)
|
||||||
|
return len(data), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *MockResponseWriter) WriteHeader(statusCode int) {
|
||||||
|
w.dataHeaderStatus = statusCode
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCheckAndWriteErrorResponse(t *testing.T) {
|
||||||
|
mockRW := MockResponseWriter{}
|
||||||
|
|
||||||
|
mockRW.WriteHeader(100)
|
||||||
|
assert.Equal(t, 100, mockRW.dataHeaderStatus)
|
||||||
|
|
||||||
|
detected := CheckAndWriteErrorResponse(&mockRW, http.StatusBadRequest, errors.New("some ERROR"))
|
||||||
|
require.True(t, detected)
|
||||||
|
require.Equal(t, http.StatusBadRequest, mockRW.dataHeaderStatus)
|
||||||
|
require.Equal(t, "some ERROR", string(mockRW.dataBody[:]))
|
||||||
|
|
||||||
|
mockRW = MockResponseWriter{}
|
||||||
|
detected = CheckAndWriteErrorResponse(&mockRW, http.StatusBadRequest, nil)
|
||||||
|
require.False(t, detected)
|
||||||
|
require.Equal(t, 0, mockRW.dataHeaderStatus)
|
||||||
|
require.Equal(t, "", string(mockRW.dataBody[:]))
|
||||||
|
}
|
|
@ -0,0 +1,100 @@
|
||||||
|
package keys
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
type testCases struct {
|
||||||
|
Keys []KeyOutput
|
||||||
|
Answers []KeyOutput
|
||||||
|
JSON [][]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTestCases() testCases {
|
||||||
|
return testCases{
|
||||||
|
[]KeyOutput{
|
||||||
|
{"A", "B", "C", "D", "E"},
|
||||||
|
{"A", "B", "C", "D", ""},
|
||||||
|
{"", "B", "C", "D", ""},
|
||||||
|
{"", "", "", "", ""},
|
||||||
|
},
|
||||||
|
make([]KeyOutput, 4),
|
||||||
|
[][]byte{
|
||||||
|
[]byte(`{"name":"A","type":"B","address":"C","pub_key":"D","mnemonic":"E"}`),
|
||||||
|
[]byte(`{"name":"A","type":"B","address":"C","pub_key":"D"}`),
|
||||||
|
[]byte(`{"name":"","type":"B","address":"C","pub_key":"D"}`),
|
||||||
|
[]byte(`{"name":"","type":"","address":"","pub_key":""}`),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMarshalJSON(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
o KeyOutput
|
||||||
|
}
|
||||||
|
|
||||||
|
data := getTestCases()
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
want []byte
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{"basic", args{data.Keys[0]}, []byte(data.JSON[0]), false},
|
||||||
|
{"mnemonic is optional", args{data.Keys[1]}, []byte(data.JSON[1]), false},
|
||||||
|
|
||||||
|
// REVIEW: Are the next results expected??
|
||||||
|
{"empty name", args{data.Keys[2]}, []byte(data.JSON[2]), false},
|
||||||
|
{"empty object", args{data.Keys[3]}, []byte(data.JSON[3]), false},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got, err := MarshalJSON(tt.args.o)
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("MarshalJSON() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Printf("%s\n", got)
|
||||||
|
if !reflect.DeepEqual(got, tt.want) {
|
||||||
|
t.Errorf("MarshalJSON() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUnmarshalJSON(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
bz []byte
|
||||||
|
ptr interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
data := getTestCases()
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{"basic", args{data.JSON[0], &data.Answers[0]}, false},
|
||||||
|
{"mnemonic is optional", args{data.JSON[1], &data.Answers[1]}, false},
|
||||||
|
|
||||||
|
// REVIEW: Are the next results expected??
|
||||||
|
{"empty name", args{data.JSON[2], &data.Answers[2]}, false},
|
||||||
|
{"empty object", args{data.JSON[3], &data.Answers[3]}, false},
|
||||||
|
}
|
||||||
|
for idx, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if err := UnmarshalJSON(tt.args.bz, tt.args.ptr); (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("UnmarshalJSON() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Confirm deserialized objects are the same
|
||||||
|
require.Equal(t, data.Keys[idx], data.Answers[idx])
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -91,6 +91,17 @@ func runDeleteCmd(cmd *cobra.Command, args []string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func confirmDeletion(buf *bufio.Reader) error {
|
||||||
|
answer, err := client.GetConfirmation("Key reference will be deleted. Continue?", buf)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !answer {
|
||||||
|
return errors.New("aborted")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////
|
////////////////////////
|
||||||
// REST
|
// REST
|
||||||
|
|
||||||
|
@ -110,42 +121,31 @@ func DeleteKeyRequestHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
err := decoder.Decode(&m)
|
err := decoder.Decode(&m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
w.Write([]byte(err.Error()))
|
_, _ = w.Write([]byte(err.Error()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
kb, err = NewKeyBaseFromHomeFlag()
|
kb, err = NewKeyBaseFromHomeFlag()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
w.Write([]byte(err.Error()))
|
_, _ = w.Write([]byte(err.Error()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = kb.Delete(name, m.Password, false)
|
err = kb.Delete(name, m.Password, false)
|
||||||
if keyerror.IsErrKeyNotFound(err) {
|
if keyerror.IsErrKeyNotFound(err) {
|
||||||
w.WriteHeader(http.StatusNotFound)
|
w.WriteHeader(http.StatusNotFound)
|
||||||
w.Write([]byte(err.Error()))
|
_, _ = w.Write([]byte(err.Error()))
|
||||||
return
|
return
|
||||||
} else if keyerror.IsErrWrongPassword(err) {
|
} else if keyerror.IsErrWrongPassword(err) {
|
||||||
w.WriteHeader(http.StatusUnauthorized)
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
w.Write([]byte(err.Error()))
|
_, _ = w.Write([]byte(err.Error()))
|
||||||
return
|
return
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
w.Write([]byte(err.Error()))
|
_, _ = w.Write([]byte(err.Error()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
}
|
}
|
||||||
|
|
||||||
func confirmDeletion(buf *bufio.Reader) error {
|
|
||||||
answer, err := client.GetConfirmation("Key reference will be deleted. Continue?", buf)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if !answer {
|
|
||||||
return errors.New("aborted")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,103 @@
|
||||||
|
package keys
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/client"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/tests"
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"github.com/tendermint/tendermint/libs/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_runDeleteCmd(t *testing.T) {
|
||||||
|
deleteKeyCommand := deleteKeyCommand()
|
||||||
|
|
||||||
|
yesF, _ := deleteKeyCommand.Flags().GetBool(flagYes)
|
||||||
|
forceF, _ := deleteKeyCommand.Flags().GetBool(flagForce)
|
||||||
|
assert.False(t, yesF)
|
||||||
|
assert.False(t, forceF)
|
||||||
|
|
||||||
|
fakeKeyName1 := "runDeleteCmd_Key1"
|
||||||
|
fakeKeyName2 := "runDeleteCmd_Key2"
|
||||||
|
|
||||||
|
// Now add a temporary keybase
|
||||||
|
kbHome, cleanUp, err := tests.GetTempDir("Test_runDeleteCmd")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
defer cleanUp()
|
||||||
|
viper.Set(cli.HomeFlag, kbHome)
|
||||||
|
|
||||||
|
// Now
|
||||||
|
kb, err := NewKeyBaseFromHomeFlag()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
_, err = kb.CreateAccount(fakeKeyName1, tests.TestMnemonic, "", "", 0, 0)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
_, err = kb.CreateAccount(fakeKeyName2, tests.TestMnemonic, "", "", 0, 1)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = runDeleteCmd(deleteKeyCommand, []string{"blah"})
|
||||||
|
require.Error(t, err)
|
||||||
|
require.Equal(t, "Key blah not found", err.Error())
|
||||||
|
|
||||||
|
// User confirmation missing
|
||||||
|
err = runDeleteCmd(deleteKeyCommand, []string{fakeKeyName1})
|
||||||
|
require.Error(t, err)
|
||||||
|
require.Equal(t, "EOF", err.Error())
|
||||||
|
|
||||||
|
{
|
||||||
|
_, err = kb.Get(fakeKeyName1)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Now there is a confirmation
|
||||||
|
cleanUp := client.OverrideStdin(bufio.NewReader(strings.NewReader("y\n")))
|
||||||
|
defer cleanUp()
|
||||||
|
err = runDeleteCmd(deleteKeyCommand, []string{fakeKeyName1})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
_, err = kb.Get(fakeKeyName1)
|
||||||
|
require.Error(t, err) // Key1 is gone
|
||||||
|
}
|
||||||
|
|
||||||
|
viper.Set(flagYes, true)
|
||||||
|
_, err = kb.Get(fakeKeyName2)
|
||||||
|
require.NoError(t, err)
|
||||||
|
err = runDeleteCmd(deleteKeyCommand, []string{fakeKeyName2})
|
||||||
|
require.NoError(t, err)
|
||||||
|
_, err = kb.Get(fakeKeyName2)
|
||||||
|
require.Error(t, err) // Key2 is gone
|
||||||
|
|
||||||
|
// TODO: Write another case for !keys.Local
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_confirmDeletion(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
buf *bufio.Reader
|
||||||
|
}
|
||||||
|
|
||||||
|
answerYes := bufio.NewReader(strings.NewReader("y\n"))
|
||||||
|
answerYes2 := bufio.NewReader(strings.NewReader("Y\n"))
|
||||||
|
answerNo := bufio.NewReader(strings.NewReader("n\n"))
|
||||||
|
answerInvalid := bufio.NewReader(strings.NewReader("245\n"))
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{"Y", args{answerYes}, false},
|
||||||
|
{"y", args{answerYes2}, false},
|
||||||
|
{"N", args{answerNo}, true},
|
||||||
|
{"BAD", args{answerInvalid}, true},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if err := confirmDeletion(tt.args.buf); (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("confirmDeletion() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,15 +6,14 @@ import (
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CMD
|
func listKeysCmd() *cobra.Command {
|
||||||
|
return &cobra.Command{
|
||||||
// listKeysCmd represents the list command
|
Use: "list",
|
||||||
var listKeysCmd = &cobra.Command{
|
Short: "List all keys",
|
||||||
Use: "list",
|
Long: `Return a list of all public keys stored by this key manager
|
||||||
Short: "List all keys",
|
|
||||||
Long: `Return a list of all public keys stored by this key manager
|
|
||||||
along with their associated name and address.`,
|
along with their associated name and address.`,
|
||||||
RunE: runListCmd,
|
RunE: runListCmd,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func runListCmd(cmd *cobra.Command, args []string) error {
|
func runListCmd(cmd *cobra.Command, args []string) error {
|
||||||
|
@ -39,13 +38,13 @@ func QueryKeysRequestHandler(indent bool) http.HandlerFunc {
|
||||||
kb, err := NewKeyBaseFromHomeFlag()
|
kb, err := NewKeyBaseFromHomeFlag()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
w.Write([]byte(err.Error()))
|
_, _ = w.Write([]byte(err.Error()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
infos, err := kb.List()
|
infos, err := kb.List()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
w.Write([]byte(err.Error()))
|
_, _ = w.Write([]byte(err.Error()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// an empty list will be JSONized as null, but we want to keep the empty list
|
// an empty list will be JSONized as null, but we want to keep the empty list
|
||||||
|
@ -56,7 +55,7 @@ func QueryKeysRequestHandler(indent bool) http.HandlerFunc {
|
||||||
keysOutput, err := Bech32KeysOutput(infos)
|
keysOutput, err := Bech32KeysOutput(infos)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
w.Write([]byte(err.Error()))
|
_, _ = w.Write([]byte(err.Error()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
PostProcessResponse(w, cdc, keysOutput, indent)
|
PostProcessResponse(w, cdc, keysOutput, indent)
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
package keys
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/tests"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
"github.com/tendermint/tendermint/libs/cli"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_runListCmd(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
cmd *cobra.Command
|
||||||
|
args []string
|
||||||
|
}
|
||||||
|
|
||||||
|
cmdBasic := listKeysCmd()
|
||||||
|
|
||||||
|
// Prepare some keybases
|
||||||
|
kbHome1, cleanUp1, err := tests.GetTempDir("Test_runListCmd")
|
||||||
|
defer cleanUp1()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
// Do nothing, leave home1 empty
|
||||||
|
|
||||||
|
kbHome2, cleanUp2, err := tests.GetTempDir("Test_runListCmd")
|
||||||
|
defer cleanUp2()
|
||||||
|
viper.Set(cli.HomeFlag, kbHome2)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
kb, err := NewKeyBaseFromHomeFlag()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
_, err = kb.CreateAccount("something", tests.TestMnemonic, "", "", 0, 0)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
testData := []struct {
|
||||||
|
name string
|
||||||
|
kbDir string
|
||||||
|
args args
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{"invalid keybase", "/dev/null", args{cmdBasic, []string{}}, true},
|
||||||
|
{"keybase: empty", kbHome1, args{cmdBasic, []string{}}, false},
|
||||||
|
{"keybase: w/key", kbHome2, args{cmdBasic, []string{}}, false},
|
||||||
|
}
|
||||||
|
for _, tt := range testData {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
viper.Set(cli.HomeFlag, tt.kbDir)
|
||||||
|
if err := runListCmd(tt.args.cmd, tt.args.args); (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("runListCmd() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -43,9 +43,7 @@ func runMnemonicCmd(cmd *cobra.Command, args []string) error {
|
||||||
if len(inputEntropy) < 43 {
|
if len(inputEntropy) < 43 {
|
||||||
return fmt.Errorf("256-bits is 43 characters in Base-64, and 100 in Base-6. You entered %v, and probably want more", len(inputEntropy))
|
return fmt.Errorf("256-bits is 43 characters in Base-64, and 100 in Base-6. You entered %v, and probably want more", len(inputEntropy))
|
||||||
}
|
}
|
||||||
conf, err := client.GetConfirmation(
|
conf, err := client.GetConfirmation(fmt.Sprintf("> Input length: %d", len(inputEntropy)), buf)
|
||||||
fmt.Sprintf("> Input length: %d", len(inputEntropy)),
|
|
||||||
buf)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
package keys
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/client"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_RunMnemonicCmdNormal(t *testing.T) {
|
||||||
|
cmdBasic := mnemonicKeyCommand()
|
||||||
|
err := runMnemonicCmd(cmdBasic, []string{})
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_RunMnemonicCmdUser(t *testing.T) {
|
||||||
|
cmdUser := mnemonicKeyCommand()
|
||||||
|
err := cmdUser.Flags().Set(flagUserEntropy, "1")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = runMnemonicCmd(cmdUser, []string{})
|
||||||
|
require.Error(t, err)
|
||||||
|
require.Equal(t, "EOF", err.Error())
|
||||||
|
|
||||||
|
// Try again
|
||||||
|
cleanUp := client.OverrideStdin(bufio.NewReader(strings.NewReader("Hi!\n")))
|
||||||
|
defer cleanUp()
|
||||||
|
err = runMnemonicCmd(cmdUser, []string{})
|
||||||
|
require.Error(t, err)
|
||||||
|
require.Equal(t,
|
||||||
|
"256-bits is 43 characters in Base-64, and 100 in Base-6. You entered 3, and probably want more",
|
||||||
|
err.Error())
|
||||||
|
|
||||||
|
// Now provide "good" entropy :)
|
||||||
|
fakeEntropy := strings.Repeat(":)", 40) + "\ny\n" // entropy + accept count
|
||||||
|
cleanUp2 := client.OverrideStdin(bufio.NewReader(strings.NewReader(fakeEntropy)))
|
||||||
|
defer cleanUp2()
|
||||||
|
err = runMnemonicCmd(cmdUser, []string{})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Now provide "good" entropy but no answer
|
||||||
|
fakeEntropy = strings.Repeat(":)", 40) + "\n" // entropy + accept count
|
||||||
|
cleanUp3 := client.OverrideStdin(bufio.NewReader(strings.NewReader(fakeEntropy)))
|
||||||
|
defer cleanUp3()
|
||||||
|
err = runMnemonicCmd(cmdUser, []string{})
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
// Now provide "good" entropy but say no
|
||||||
|
fakeEntropy = strings.Repeat(":)", 40) + "\nn\n" // entropy + accept count
|
||||||
|
cleanUp4 := client.OverrideStdin(bufio.NewReader(strings.NewReader(fakeEntropy)))
|
||||||
|
defer cleanUp4()
|
||||||
|
err = runMnemonicCmd(cmdUser, []string{})
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
|
@ -22,7 +22,7 @@ func Commands() *cobra.Command {
|
||||||
cmd.AddCommand(
|
cmd.AddCommand(
|
||||||
mnemonicKeyCommand(),
|
mnemonicKeyCommand(),
|
||||||
addKeyCommand(),
|
addKeyCommand(),
|
||||||
listKeysCmd,
|
listKeysCmd(),
|
||||||
showKeysCmd(),
|
showKeysCmd(),
|
||||||
client.LineBreak,
|
client.LineBreak,
|
||||||
deleteKeyCommand(),
|
deleteKeyCommand(),
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
package keys
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
"github.com/gorilla/mux"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCommands(t *testing.T) {
|
||||||
|
rootCommands := Commands()
|
||||||
|
assert.NotNil(t, rootCommands)
|
||||||
|
|
||||||
|
// Commands are registered
|
||||||
|
assert.Equal(t, 7, len(rootCommands.Commands()))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRegisterRoutes(t *testing.T) {
|
||||||
|
fakeRouter := mux.Router{}
|
||||||
|
RegisterRoutes(&fakeRouter, false)
|
||||||
|
}
|
|
@ -93,7 +93,12 @@ func runShowCmd(cmd *cobra.Command, args []string) (err error) {
|
||||||
|
|
||||||
isShowAddr := viper.GetBool(FlagAddress)
|
isShowAddr := viper.GetBool(FlagAddress)
|
||||||
isShowPubKey := viper.GetBool(FlagPublicKey)
|
isShowPubKey := viper.GetBool(FlagPublicKey)
|
||||||
isOutputSet := cmd.Flag(cli.OutputFlag).Changed
|
|
||||||
|
isOutputSet := false
|
||||||
|
tmp := cmd.Flag(cli.OutputFlag)
|
||||||
|
if tmp != nil {
|
||||||
|
isOutputSet = tmp.Changed
|
||||||
|
}
|
||||||
|
|
||||||
if isShowAddr && isShowPubKey {
|
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")
|
||||||
|
@ -161,25 +166,25 @@ func GetKeyRequestHandler(indent bool) http.HandlerFunc {
|
||||||
bechKeyOut, err := getBechKeyOut(bechPrefix)
|
bechKeyOut, err := getBechKeyOut(bechPrefix)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
w.Write([]byte(err.Error()))
|
_, _ = w.Write([]byte(err.Error()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
info, err := GetKeyInfo(name)
|
info, err := GetKeyInfo(name)
|
||||||
if keyerror.IsErrKeyNotFound(err) {
|
if keyerror.IsErrKeyNotFound(err) {
|
||||||
w.WriteHeader(http.StatusNotFound)
|
w.WriteHeader(http.StatusNotFound)
|
||||||
w.Write([]byte(err.Error()))
|
_, _ = w.Write([]byte(err.Error()))
|
||||||
return
|
return
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
w.Write([]byte(err.Error()))
|
_, _ = w.Write([]byte(err.Error()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
keyOutput, err := bechKeyOut(info)
|
keyOutput, err := bechKeyOut(info)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
w.Write([]byte(err.Error()))
|
_, _ = w.Write([]byte(err.Error()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,146 @@
|
||||||
|
package keys
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/tests"
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
"github.com/tendermint/tendermint/libs/cli"
|
||||||
|
|
||||||
|
"github.com/tendermint/tendermint/crypto/secp256k1"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/crypto/keys"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_multiSigKey_Properties(t *testing.T) {
|
||||||
|
tmpKey1 := secp256k1.GenPrivKeySecp256k1([]byte("mySecret"))
|
||||||
|
|
||||||
|
tmp := multiSigKey{
|
||||||
|
name: "myMultisig",
|
||||||
|
key: tmpKey1.PubKey(),
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, "myMultisig", tmp.GetName())
|
||||||
|
assert.Equal(t, keys.TypeLocal, tmp.GetType())
|
||||||
|
assert.Equal(t, "015ABFFB09DB738A45745A91E8C401423ECE4016", tmp.GetPubKey().Address().String())
|
||||||
|
assert.Equal(t, "cosmos1q9dtl7cfmdec53t5t2g733qpgglvusqk6xdntl", tmp.GetAddress().String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_showKeysCmd(t *testing.T) {
|
||||||
|
cmd := showKeysCmd()
|
||||||
|
assert.NotNil(t, cmd)
|
||||||
|
assert.Equal(t, "false", cmd.Flag(FlagAddress).DefValue)
|
||||||
|
assert.Equal(t, "false", cmd.Flag(FlagPublicKey).DefValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_runShowCmd(t *testing.T) {
|
||||||
|
cmd := showKeysCmd()
|
||||||
|
|
||||||
|
err := runShowCmd(cmd, []string{"invalid"})
|
||||||
|
assert.EqualError(t, err, "Key invalid not found")
|
||||||
|
|
||||||
|
err = runShowCmd(cmd, []string{"invalid1", "invalid2"})
|
||||||
|
assert.EqualError(t, err, "Key invalid1 not found")
|
||||||
|
|
||||||
|
// Prepare a key base
|
||||||
|
// Now add a temporary keybase
|
||||||
|
kbHome, cleanUp, err := tests.GetTempDir("Test_runShowCmd")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
defer cleanUp()
|
||||||
|
viper.Set(cli.HomeFlag, kbHome)
|
||||||
|
|
||||||
|
fakeKeyName1 := "runShowCmd_Key1"
|
||||||
|
fakeKeyName2 := "runShowCmd_Key2"
|
||||||
|
kb, err := NewKeyBaseFromHomeFlag()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
_, err = kb.CreateAccount(fakeKeyName1, tests.TestMnemonic, "", "", 0, 0)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
_, err = kb.CreateAccount(fakeKeyName2, tests.TestMnemonic, "", "", 0, 1)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
// Now try single key
|
||||||
|
err = runShowCmd(cmd, []string{fakeKeyName1})
|
||||||
|
assert.EqualError(t, err, "invalid Bech32 prefix encoding provided: ")
|
||||||
|
|
||||||
|
// Now try single key - set bech to acc
|
||||||
|
viper.Set(FlagBechPrefix, "acc")
|
||||||
|
err = runShowCmd(cmd, []string{fakeKeyName1})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
// Now try multisig key - set bech to acc
|
||||||
|
viper.Set(FlagBechPrefix, "acc")
|
||||||
|
err = runShowCmd(cmd, []string{fakeKeyName1, fakeKeyName2})
|
||||||
|
assert.EqualError(t, err, "threshold must be a positive integer")
|
||||||
|
|
||||||
|
// Now try multisig key - set bech to acc + threshold=2
|
||||||
|
viper.Set(FlagBechPrefix, "acc")
|
||||||
|
viper.Set(flagMultiSigThreshold, 2)
|
||||||
|
err = runShowCmd(cmd, []string{fakeKeyName1, fakeKeyName2})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
// TODO: Capture stdout and compare
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_validateMultisigThreshold(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
k int
|
||||||
|
nKeys int
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{"zeros", args{0, 0}, true},
|
||||||
|
{"1-0", args{1, 0}, true},
|
||||||
|
{"1-1", args{1, 1}, false},
|
||||||
|
{"1-2", args{1, 1}, false},
|
||||||
|
{"1-2", args{2, 1}, true},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if err := validateMultisigThreshold(tt.args.k, tt.args.nKeys); (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("validateMultisigThreshold() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_getBechKeyOut(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
bechPrefix string
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
want bechKeyOutFn
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{"empty", args{""}, nil, true},
|
||||||
|
{"wrong", args{"???"}, nil, true},
|
||||||
|
{"acc", args{"acc"}, Bech32KeyOutput, false},
|
||||||
|
{"val", args{"val"}, Bech32ValKeyOutput, false},
|
||||||
|
{"cons", args{"cons"}, Bech32ConsKeyOutput, false},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got, err := getBechKeyOut(tt.args.bechPrefix)
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("getBechKeyOut() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !tt.wantErr {
|
||||||
|
assert.NotNil(t, got)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Still not possible to compare functions
|
||||||
|
// Maybe in next release: https://github.com/stretchr/testify/issues/182
|
||||||
|
//if &got != &tt.want {
|
||||||
|
// t.Errorf("getBechKeyOut() = %v, want %v", got, tt.want)
|
||||||
|
//}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,7 +8,7 @@ import (
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/client"
|
"github.com/cosmos/cosmos-sdk/client"
|
||||||
keys "github.com/cosmos/cosmos-sdk/crypto/keys"
|
"github.com/cosmos/cosmos-sdk/crypto/keys"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
@ -73,14 +73,14 @@ func UpdateKeyRequestHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
err := decoder.Decode(&m)
|
err := decoder.Decode(&m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
w.Write([]byte(err.Error()))
|
_, _ = w.Write([]byte(err.Error()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
kb, err = NewKeyBaseFromHomeFlag()
|
kb, err = NewKeyBaseFromHomeFlag()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
w.Write([]byte(err.Error()))
|
_, _ = w.Write([]byte(err.Error()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,15 +89,15 @@ func UpdateKeyRequestHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
err = kb.Update(name, m.OldPassword, getNewpass)
|
err = kb.Update(name, m.OldPassword, getNewpass)
|
||||||
if keyerror.IsErrKeyNotFound(err) {
|
if keyerror.IsErrKeyNotFound(err) {
|
||||||
w.WriteHeader(http.StatusNotFound)
|
w.WriteHeader(http.StatusNotFound)
|
||||||
w.Write([]byte(err.Error()))
|
_, _ = w.Write([]byte(err.Error()))
|
||||||
return
|
return
|
||||||
} else if keyerror.IsErrWrongPassword(err) {
|
} else if keyerror.IsErrWrongPassword(err) {
|
||||||
w.WriteHeader(http.StatusUnauthorized)
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
w.Write([]byte(err.Error()))
|
_, _ = w.Write([]byte(err.Error()))
|
||||||
return
|
return
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
w.Write([]byte(err.Error()))
|
_, _ = w.Write([]byte(err.Error()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
package keys
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/client"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/tests"
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
"github.com/tendermint/tendermint/libs/cli"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_updateKeyCommand(t *testing.T) {
|
||||||
|
cmd := updateKeyCommand()
|
||||||
|
assert.NotNil(t, cmd)
|
||||||
|
// No flags or defaults to validate
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_runUpdateCmd(t *testing.T) {
|
||||||
|
fakeKeyName1 := "runUpdateCmd_Key1"
|
||||||
|
fakeKeyName2 := "runUpdateCmd_Key2"
|
||||||
|
|
||||||
|
cmd := updateKeyCommand()
|
||||||
|
|
||||||
|
// fails because it requests a password
|
||||||
|
err := runUpdateCmd(cmd, []string{fakeKeyName1})
|
||||||
|
assert.EqualError(t, err, "EOF")
|
||||||
|
|
||||||
|
cleanUp := client.OverrideStdin(bufio.NewReader(strings.NewReader("pass1234\n")))
|
||||||
|
defer cleanUp()
|
||||||
|
|
||||||
|
// try again
|
||||||
|
err = runUpdateCmd(cmd, []string{fakeKeyName1})
|
||||||
|
assert.EqualError(t, err, "Key runUpdateCmd_Key1 not found")
|
||||||
|
|
||||||
|
// Prepare a key base
|
||||||
|
// Now add a temporary keybase
|
||||||
|
kbHome, cleanUp1, err := tests.GetTempDir("Test_runShowCmd")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
defer cleanUp1()
|
||||||
|
viper.Set(cli.HomeFlag, kbHome)
|
||||||
|
|
||||||
|
kb, err := NewKeyBaseFromHomeFlag()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
_, err = kb.CreateAccount(fakeKeyName1, tests.TestMnemonic, "", "", 0, 0)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
_, err = kb.CreateAccount(fakeKeyName2, tests.TestMnemonic, "", "", 0, 1)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
// Try again now that we have keys
|
||||||
|
cleanUp2 := client.OverrideStdin(bufio.NewReader(strings.NewReader("pass1234\nNew1234\nNew1234")))
|
||||||
|
defer cleanUp2()
|
||||||
|
|
||||||
|
// Incorrect key type
|
||||||
|
err = runUpdateCmd(cmd, []string{fakeKeyName1})
|
||||||
|
assert.EqualError(t, err, "locally stored key required. Received: keys.offlineInfo")
|
||||||
|
|
||||||
|
// TODO: Check for other type types?
|
||||||
|
|
||||||
|
}
|
|
@ -15,7 +15,11 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// KeyDBName is the directory under root where we store the keys
|
// KeyDBName is the directory under root where we store the keys
|
||||||
const KeyDBName = "keys"
|
const (
|
||||||
|
KeyDBName = "keys"
|
||||||
|
OutputFormatText = "text"
|
||||||
|
OutputFormatJSON = "json"
|
||||||
|
)
|
||||||
|
|
||||||
type bechKeyOutFn func(keyInfo keys.Info) (KeyOutput, error)
|
type bechKeyOutFn func(keyInfo keys.Info) (KeyOutput, error)
|
||||||
|
|
||||||
|
@ -157,7 +161,7 @@ func printKeyInfo(keyInfo keys.Info, bechKeyOut bechKeyOutFn) {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch viper.Get(cli.OutputFlag) {
|
switch viper.Get(cli.OutputFlag) {
|
||||||
case "text":
|
case OutputFormatText:
|
||||||
fmt.Printf("NAME:\tTYPE:\tADDRESS:\t\t\t\t\t\tPUBKEY:\n")
|
fmt.Printf("NAME:\tTYPE:\tADDRESS:\t\t\t\t\t\tPUBKEY:\n")
|
||||||
printKeyOutput(ko)
|
printKeyOutput(ko)
|
||||||
case "json":
|
case "json":
|
||||||
|
@ -176,12 +180,12 @@ func printInfos(infos []keys.Info) {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
switch viper.Get(cli.OutputFlag) {
|
switch viper.Get(cli.OutputFlag) {
|
||||||
case "text":
|
case OutputFormatText:
|
||||||
fmt.Printf("NAME:\tTYPE:\tADDRESS:\t\t\t\t\t\tPUBKEY:\n")
|
fmt.Printf("NAME:\tTYPE:\tADDRESS:\t\t\t\t\t\tPUBKEY:\n")
|
||||||
for _, ko := range kos {
|
for _, ko := range kos {
|
||||||
printKeyOutput(ko)
|
printKeyOutput(ko)
|
||||||
}
|
}
|
||||||
case "json":
|
case OutputFormatJSON:
|
||||||
out, err := MarshalJSON(kos)
|
out, err := MarshalJSON(kos)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
@ -225,12 +229,12 @@ func PostProcessResponse(w http.ResponseWriter, cdc *codec.Codec, response inter
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
w.Write([]byte(err.Error()))
|
_, _ = w.Write([]byte(err.Error()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case []byte:
|
case []byte:
|
||||||
output = response.([]byte)
|
output = response.([]byte)
|
||||||
}
|
}
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
w.Write(output)
|
_, _ = w.Write(output)
|
||||||
}
|
}
|
||||||
|
|
|
@ -175,7 +175,7 @@ func TestVersion(t *testing.T) {
|
||||||
reg, err := regexp.Compile(`\d+\.\d+\.\d+.*`)
|
reg, err := regexp.Compile(`\d+\.\d+\.\d+.*`)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
match := reg.MatchString(body)
|
match := reg.MatchString(body)
|
||||||
require.True(t, match, body, fmt.Sprintf("%s", body))
|
require.True(t, match, body, body)
|
||||||
|
|
||||||
// node info
|
// node info
|
||||||
res, body = Request(t, port, "GET", "/node_version", nil)
|
res, body = Request(t, port, "GET", "/node_version", nil)
|
||||||
|
|
|
@ -301,8 +301,8 @@ func fauxMerkleModeOpt(bapp *baseapp.BaseApp) {
|
||||||
// /usr/local/go/bin/go test -benchmem -run=^$ github.com/cosmos/cosmos-sdk/cmd/gaia/app -bench ^BenchmarkFullGaiaSimulation$ -SimulationCommit=true -cpuprofile cpu.out
|
// /usr/local/go/bin/go test -benchmem -run=^$ github.com/cosmos/cosmos-sdk/cmd/gaia/app -bench ^BenchmarkFullGaiaSimulation$ -SimulationCommit=true -cpuprofile cpu.out
|
||||||
func BenchmarkFullGaiaSimulation(b *testing.B) {
|
func BenchmarkFullGaiaSimulation(b *testing.B) {
|
||||||
// Setup Gaia application
|
// Setup Gaia application
|
||||||
var logger log.Logger
|
logger := log.NewNopLogger()
|
||||||
logger = log.NewNopLogger()
|
|
||||||
var db dbm.DB
|
var db dbm.DB
|
||||||
dir, _ := ioutil.TempDir("", "goleveldb-gaia-sim")
|
dir, _ := ioutil.TempDir("", "goleveldb-gaia-sim")
|
||||||
db, _ = dbm.NewGoLevelDB("Simulation", dir)
|
db, _ = dbm.NewGoLevelDB("Simulation", dir)
|
||||||
|
|
|
@ -8,20 +8,16 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/tendermint/tendermint/libs/cli"
|
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/client"
|
"github.com/cosmos/cosmos-sdk/client"
|
||||||
"github.com/cosmos/cosmos-sdk/cmd/gaia/app"
|
"github.com/cosmos/cosmos-sdk/cmd/gaia/app"
|
||||||
|
"github.com/cosmos/cosmos-sdk/server"
|
||||||
|
"github.com/cosmos/cosmos-sdk/server/mock"
|
||||||
|
"github.com/spf13/viper"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
abciServer "github.com/tendermint/tendermint/abci/server"
|
abciServer "github.com/tendermint/tendermint/abci/server"
|
||||||
tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands"
|
tcmd "github.com/tendermint/tendermint/cmd/tendermint/commands"
|
||||||
|
"github.com/tendermint/tendermint/libs/cli"
|
||||||
"github.com/tendermint/tendermint/libs/log"
|
"github.com/tendermint/tendermint/libs/log"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/server"
|
|
||||||
"github.com/cosmos/cosmos-sdk/server/mock"
|
|
||||||
|
|
||||||
"github.com/spf13/viper"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestInitCmd(t *testing.T) {
|
func TestInitCmd(t *testing.T) {
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"errors"
|
"errors"
|
||||||
|
@ -147,13 +148,13 @@ func (kb dbKeybase) CreateLedger(name string, algo SigningAlgo, account uint32,
|
||||||
}
|
}
|
||||||
pub := priv.PubKey()
|
pub := priv.PubKey()
|
||||||
|
|
||||||
return kb.writeLedgerKey(pub, *hdPath, name), nil
|
return kb.writeLedgerKey(name, pub, *hdPath), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateOffline creates a new reference to an offline keypair
|
// CreateOffline creates a new reference to an offline keypair
|
||||||
// It returns the created key info
|
// It returns the created key info
|
||||||
func (kb dbKeybase) CreateOffline(name string, pub tmcrypto.PubKey) (Info, error) {
|
func (kb dbKeybase) CreateOffline(name string, pub tmcrypto.PubKey) (Info, error) {
|
||||||
return kb.writeOfflineKey(pub, name), nil
|
return kb.writeOfflineKey(name, pub), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (kb *dbKeybase) persistDerivedKey(seed []byte, passwd, name, fullHdPath string) (info Info, err error) {
|
func (kb *dbKeybase) persistDerivedKey(seed []byte, passwd, name, fullHdPath string) (info Info, err error) {
|
||||||
|
@ -167,10 +168,10 @@ func (kb *dbKeybase) persistDerivedKey(seed []byte, passwd, name, fullHdPath str
|
||||||
// if we have a password, use it to encrypt the private key and store it
|
// if we have a password, use it to encrypt the private key and store it
|
||||||
// else store the public key only
|
// else store the public key only
|
||||||
if passwd != "" {
|
if passwd != "" {
|
||||||
info = kb.writeLocalKey(secp256k1.PrivKeySecp256k1(derivedPriv), name, passwd)
|
info = kb.writeLocalKey(name, secp256k1.PrivKeySecp256k1(derivedPriv), passwd)
|
||||||
} else {
|
} else {
|
||||||
pubk := secp256k1.PrivKeySecp256k1(derivedPriv).PubKey()
|
pubk := secp256k1.PrivKeySecp256k1(derivedPriv).PubKey()
|
||||||
info = kb.writeOfflineKey(pubk, name)
|
info = kb.writeOfflineKey(name, pubk)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -342,7 +343,7 @@ func (kb dbKeybase) ImportPubKey(name string, armor string) (err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
kb.writeOfflineKey(pubKey, name)
|
kb.writeOfflineKey(name, pubKey)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -390,10 +391,10 @@ func (kb dbKeybase) Update(name, oldpass string, getNewpass func() (string, erro
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
kb.writeLocalKey(key, name, newpass)
|
kb.writeLocalKey(name, key, newpass)
|
||||||
return nil
|
return nil
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("locally stored key required")
|
return fmt.Errorf("locally stored key required. Received: %v", reflect.TypeOf(info).String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -402,29 +403,29 @@ func (kb dbKeybase) CloseDB() {
|
||||||
kb.db.Close()
|
kb.db.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (kb dbKeybase) writeLocalKey(priv tmcrypto.PrivKey, name, passphrase string) Info {
|
func (kb dbKeybase) writeLocalKey(name string, priv tmcrypto.PrivKey, passphrase string) Info {
|
||||||
// encrypt private key using passphrase
|
// encrypt private key using passphrase
|
||||||
privArmor := mintkey.EncryptArmorPrivKey(priv, passphrase)
|
privArmor := mintkey.EncryptArmorPrivKey(priv, passphrase)
|
||||||
// make Info
|
// make Info
|
||||||
pub := priv.PubKey()
|
pub := priv.PubKey()
|
||||||
info := newLocalInfo(name, pub, privArmor)
|
info := newLocalInfo(name, pub, privArmor)
|
||||||
kb.writeInfo(info, name)
|
kb.writeInfo(name, info)
|
||||||
return info
|
return info
|
||||||
}
|
}
|
||||||
|
|
||||||
func (kb dbKeybase) writeLedgerKey(pub tmcrypto.PubKey, path hd.BIP44Params, name string) Info {
|
func (kb dbKeybase) writeLedgerKey(name string, pub tmcrypto.PubKey, path hd.BIP44Params) Info {
|
||||||
info := newLedgerInfo(name, pub, path)
|
info := newLedgerInfo(name, pub, path)
|
||||||
kb.writeInfo(info, name)
|
kb.writeInfo(name, info)
|
||||||
return info
|
return info
|
||||||
}
|
}
|
||||||
|
|
||||||
func (kb dbKeybase) writeOfflineKey(pub tmcrypto.PubKey, name string) Info {
|
func (kb dbKeybase) writeOfflineKey(name string, pub tmcrypto.PubKey) Info {
|
||||||
info := newOfflineInfo(name, pub)
|
info := newOfflineInfo(name, pub)
|
||||||
kb.writeInfo(info, name)
|
kb.writeInfo(name, info)
|
||||||
return info
|
return info
|
||||||
}
|
}
|
||||||
|
|
||||||
func (kb dbKeybase) writeInfo(info Info, name string) {
|
func (kb dbKeybase) writeInfo(name string, info Info) {
|
||||||
// write the info by key
|
// write the info by key
|
||||||
key := infoKey(name)
|
key := infoKey(name)
|
||||||
kb.db.SetSync(key, writeInfo(info))
|
kb.db.SetSync(key, writeInfo(info))
|
||||||
|
|
|
@ -2,6 +2,7 @@ package keys
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
@ -9,26 +10,84 @@ import (
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/crypto/keys/hd"
|
"github.com/cosmos/cosmos-sdk/crypto/keys/hd"
|
||||||
"github.com/cosmos/cosmos-sdk/crypto/keys/mintkey"
|
"github.com/cosmos/cosmos-sdk/crypto/keys/mintkey"
|
||||||
|
"github.com/cosmos/cosmos-sdk/types"
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
"github.com/tendermint/tendermint/crypto"
|
"github.com/tendermint/tendermint/crypto"
|
||||||
"github.com/tendermint/tendermint/crypto/ed25519"
|
"github.com/tendermint/tendermint/crypto/ed25519"
|
||||||
|
|
||||||
dbm "github.com/tendermint/tendermint/libs/db"
|
dbm "github.com/tendermint/tendermint/libs/db"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/types"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
mintkey.BcryptSecurityParameter = 1
|
mintkey.BcryptSecurityParameter = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestKeybaseOpenClose(t *testing.T) {
|
||||||
|
dir, err := ioutil.TempDir("", "TestKeybaseOpenClose")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
kb := New(dbm.NewDB("TestKeybaseOpenClose", dbm.LevelDBBackend, dir))
|
||||||
|
kb.CloseDB()
|
||||||
|
|
||||||
|
// The DB has been closed. At the moment, the expected behaviour is to panic
|
||||||
|
assert.Panics(t, func() {
|
||||||
|
_, _ = kb.CreateAccount(
|
||||||
|
"some_account",
|
||||||
|
"key pair crucial catch public canyon evil outer stage ten gym tornado",
|
||||||
|
"", "", 0, 1)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLanguage(t *testing.T) {
|
||||||
|
kb := New(dbm.NewMemDB())
|
||||||
|
_, _, err := kb.CreateMnemonic("something", Japanese, "no_pass", Secp256k1)
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.Equal(t, "unsupported language: only english is supported", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateAccountInvalidMnemonic(t *testing.T) {
|
||||||
|
kb := New(dbm.NewMemDB())
|
||||||
|
_, err := kb.CreateAccount(
|
||||||
|
"some_account",
|
||||||
|
"malarkey pair crucial catch public canyon evil outer stage ten gym tornado",
|
||||||
|
"", "", 0, 1)
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.Equal(t, "Invalid mnemonic", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateLedgerUnsupportedAlgo(t *testing.T) {
|
||||||
|
kb := New(dbm.NewMemDB())
|
||||||
|
_, err := kb.CreateLedger("some_account", Ed25519, 0, 1)
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.Equal(t, "unsupported signing algo: only secp256k1 is supported", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateLedger(t *testing.T) {
|
||||||
|
kb := New(dbm.NewMemDB())
|
||||||
|
|
||||||
|
// test_cover and test_unit will result in different answers
|
||||||
|
// test_cover does not compile some dependencies so ledger is disabled
|
||||||
|
// test_unit may add a ledger mock
|
||||||
|
// both cases are acceptable
|
||||||
|
ledger, err := kb.CreateLedger("some_account", Secp256k1, 0, 1)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.Equal(t, "ledger nano S: support for ledger devices is not available in this executable", err.Error())
|
||||||
|
assert.Nil(t, ledger)
|
||||||
|
} else {
|
||||||
|
// The mock is available, check that the address is correct
|
||||||
|
pubKey := ledger.GetPubKey()
|
||||||
|
addr, err := sdk.Bech32ifyAccPub(pubKey)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, "cosmospub1addwnpepqfsdqjr68h7wjg5wacksmqaypasnra232fkgu5sxdlnlu8j22ztxvlqvd65", addr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TestKeyManagement makes sure we can manipulate these keys well
|
// TestKeyManagement makes sure we can manipulate these keys well
|
||||||
func TestKeyManagement(t *testing.T) {
|
func TestKeyManagement(t *testing.T) {
|
||||||
// make the storage with reasonable defaults
|
// make the storage with reasonable defaults
|
||||||
db := dbm.NewMemDB()
|
db := dbm.NewMemDB()
|
||||||
cstore := New(
|
cstore := New(db)
|
||||||
db,
|
|
||||||
)
|
|
||||||
|
|
||||||
algo := Secp256k1
|
algo := Secp256k1
|
||||||
n1, n2, n3 := "personal", "business", "other"
|
n1, n2, n3 := "personal", "business", "other"
|
||||||
|
@ -112,9 +171,7 @@ func TestKeyManagement(t *testing.T) {
|
||||||
// TestSignVerify does some detailed checks on how we sign and validate
|
// TestSignVerify does some detailed checks on how we sign and validate
|
||||||
// signatures
|
// signatures
|
||||||
func TestSignVerify(t *testing.T) {
|
func TestSignVerify(t *testing.T) {
|
||||||
cstore := New(
|
cstore := New(dbm.NewMemDB())
|
||||||
dbm.NewMemDB(),
|
|
||||||
)
|
|
||||||
algo := Secp256k1
|
algo := Secp256k1
|
||||||
|
|
||||||
n1, n2, n3 := "some dude", "a dudette", "dude-ish"
|
n1, n2, n3 := "some dude", "a dudette", "dude-ish"
|
||||||
|
|
|
@ -1,157 +0,0 @@
|
||||||
// +build cgo,ledger,test_real_ledger
|
|
||||||
|
|
||||||
package crypto
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/crypto/keys/hd"
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
"github.com/tendermint/tendermint/crypto/encoding/amino"
|
|
||||||
ledger "github.com/zondax/ledger-cosmos-go"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// These tests expect a ledger device initialized to the following mnemonic
|
|
||||||
testMnemonic = "equip will roof matter pink blind book anxiety banner elbow sun young"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestDiscoverDevice(t *testing.T) {
|
|
||||||
device, err := discoverLedger()
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.NotNil(t, device)
|
|
||||||
defer device.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDiscoverDeviceTwice(t *testing.T) {
|
|
||||||
// We expect the second call not to find a device
|
|
||||||
device, err := discoverLedger()
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.NotNil(t, device)
|
|
||||||
defer device.Close()
|
|
||||||
|
|
||||||
device2, err := discoverLedger()
|
|
||||||
require.Error(t, err)
|
|
||||||
require.Equal(t, "no ledger connected", err.Error())
|
|
||||||
require.Nil(t, device2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDiscoverDeviceTwiceClosing(t *testing.T) {
|
|
||||||
{
|
|
||||||
device, err := ledger.FindLedgerCosmosUserApp()
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.NotNil(t, device)
|
|
||||||
require.NoError(t, device.Close())
|
|
||||||
}
|
|
||||||
|
|
||||||
device2, err := discoverLedger()
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.NotNil(t, device2)
|
|
||||||
require.NoError(t, device2.Close())
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPublicKey(t *testing.T) {
|
|
||||||
path := *hd.NewFundraiserParams(0, 0)
|
|
||||||
priv, err := NewPrivKeyLedgerSecp256k1(path)
|
|
||||||
require.Nil(t, err, "%s", err)
|
|
||||||
require.NotNil(t, priv)
|
|
||||||
|
|
||||||
pubKeyAddr, err := sdk.Bech32ifyAccPub(priv.PubKey())
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.Equal(t, "cosmospub1addwnpepqd87l8xhcnrrtzxnkql7k55ph8fr9jarf4hn6udwukfprlalu8lgw0urza0", pubKeyAddr, "Is your device using test mnemonic: %s ?", testMnemonic)
|
|
||||||
require.Equal(t, "5075624b6579536563703235366b317b303334464546394344374334433633353838443342303"+
|
|
||||||
"3464542353238314239443233324342413334443646334437314145453539323131464642464531464538377d",
|
|
||||||
fmt.Sprintf("%x", priv.PubKey()))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPublicKeyHDPath(t *testing.T) {
|
|
||||||
expectedAnswers := []string{
|
|
||||||
"cosmospub1addwnpepqd87l8xhcnrrtzxnkql7k55ph8fr9jarf4hn6udwukfprlalu8lgw0urza0",
|
|
||||||
"cosmospub1addwnpepqfsdqjr68h7wjg5wacksmqaypasnra232fkgu5sxdlnlu8j22ztxvlqvd65",
|
|
||||||
"cosmospub1addwnpepqw3xwqun6q43vtgw6p4qspq7srvxhcmvq4jrx5j5ma6xy3r7k6dtxmrkh3d",
|
|
||||||
"cosmospub1addwnpepqvez9lrp09g8w7gkv42y4yr5p6826cu28ydrhrujv862yf4njmqyyjr4pjs",
|
|
||||||
"cosmospub1addwnpepq06hw3enfrtmq8n67teytcmtnrgcr0yntmyt25kdukfjkerdc7lqg32rcz7",
|
|
||||||
"cosmospub1addwnpepqg3trf2gd0s2940nckrxherwqhgmm6xd5h4pcnrh4x7y35h6yafmcpk5qns",
|
|
||||||
"cosmospub1addwnpepqdm6rjpx6wsref8wjn7ym6ntejet430j4szpngfgc20caz83lu545vuv8hp",
|
|
||||||
"cosmospub1addwnpepqvdhtjzy2wf44dm03jxsketxc07vzqwvt3vawqqtljgsr9s7jvydjmt66ew",
|
|
||||||
"cosmospub1addwnpepqwystfpyxwcava7v3t7ndps5xzu6s553wxcxzmmnxevlzvwrlqpzz695nw9",
|
|
||||||
"cosmospub1addwnpepqw970u6gjqkccg9u3rfj99857wupj2z9fqfzy2w7e5dd7xn7kzzgkgqch0r",
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check with device
|
|
||||||
for i := uint32(0); i < 10; i++ {
|
|
||||||
path := *hd.NewFundraiserParams(0, i)
|
|
||||||
fmt.Printf("Checking keys at %v\n", path)
|
|
||||||
|
|
||||||
priv, err := NewPrivKeyLedgerSecp256k1(path)
|
|
||||||
require.Nil(t, err, "%s", err)
|
|
||||||
require.NotNil(t, priv)
|
|
||||||
|
|
||||||
pubKeyAddr, err := sdk.Bech32ifyAccPub(priv.PubKey())
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.Equal(t, expectedAnswers[i], pubKeyAddr, "Is your device using test mnemonic: %s ?", testMnemonic)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func getFakeTx(accountNumber uint32) []byte {
|
|
||||||
tmp := fmt.Sprintf(
|
|
||||||
`{"account_number":"%d","chain_id":"1234","fee":{"amount":[{"amount":"150","denom":"atom"}],"gas":"5000"},"memo":"memo","msgs":[[""]],"sequence":"6"}`,
|
|
||||||
accountNumber)
|
|
||||||
|
|
||||||
return []byte(tmp)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSignaturesHD(t *testing.T) {
|
|
||||||
for account := uint32(0); account < 100; account += 30 {
|
|
||||||
msg := getFakeTx(account)
|
|
||||||
|
|
||||||
path := *hd.NewFundraiserParams(account, account/5)
|
|
||||||
fmt.Printf("Checking signature at %v\n", path)
|
|
||||||
|
|
||||||
priv, err := NewPrivKeyLedgerSecp256k1(path)
|
|
||||||
require.Nil(t, err, "%s", err)
|
|
||||||
|
|
||||||
pub := priv.PubKey()
|
|
||||||
sig, err := priv.Sign(msg)
|
|
||||||
require.Nil(t, err)
|
|
||||||
|
|
||||||
valid := pub.VerifyBytes(msg, sig)
|
|
||||||
require.True(t, valid, "Is your device using test mnemonic: %s ?", testMnemonic)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRealLedgerSecp256k1(t *testing.T) {
|
|
||||||
msg := getFakeTx(50)
|
|
||||||
path := *hd.NewFundraiserParams(0, 0)
|
|
||||||
priv, err := NewPrivKeyLedgerSecp256k1(path)
|
|
||||||
require.Nil(t, err, "%s", err)
|
|
||||||
|
|
||||||
pub := priv.PubKey()
|
|
||||||
sig, err := priv.Sign(msg)
|
|
||||||
require.Nil(t, err)
|
|
||||||
|
|
||||||
valid := pub.VerifyBytes(msg, sig)
|
|
||||||
require.True(t, valid)
|
|
||||||
|
|
||||||
// now, let's serialize the public key and make sure it still works
|
|
||||||
bs := priv.PubKey().Bytes()
|
|
||||||
pub2, err := cryptoAmino.PubKeyFromBytes(bs)
|
|
||||||
require.Nil(t, err, "%+v", err)
|
|
||||||
|
|
||||||
// make sure we get the same pubkey when we load from disk
|
|
||||||
require.Equal(t, pub, pub2)
|
|
||||||
|
|
||||||
// signing with the loaded key should match the original pubkey
|
|
||||||
sig, err = priv.Sign(msg)
|
|
||||||
require.Nil(t, err)
|
|
||||||
valid = pub.VerifyBytes(msg, sig)
|
|
||||||
require.True(t, valid)
|
|
||||||
|
|
||||||
// make sure pubkeys serialize properly as well
|
|
||||||
bs = pub.Bytes()
|
|
||||||
bpub, err := cryptoAmino.PubKeyFromBytes(bs)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.Equal(t, pub, bpub)
|
|
||||||
}
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
// +build ledger,test_ledger_mock
|
||||||
|
|
||||||
|
package crypto
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/btcsuite/btcd/btcec"
|
||||||
|
"github.com/cosmos/cosmos-sdk/crypto/keys/hd"
|
||||||
|
"github.com/cosmos/cosmos-sdk/tests"
|
||||||
|
"github.com/cosmos/go-bip39"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
secp256k1 "github.com/tendermint/btcd/btcec"
|
||||||
|
"github.com/tendermint/tendermint/crypto"
|
||||||
|
)
|
||||||
|
|
||||||
|
// If ledger support (build tag) has been enabled, which implies a CGO dependency,
|
||||||
|
// set the discoverLedger function which is responsible for loading the Ledger
|
||||||
|
// device at runtime or returning an error.
|
||||||
|
func init() {
|
||||||
|
discoverLedger = func() (LedgerSECP256K1, error) {
|
||||||
|
return LedgerSECP256K1Mock{}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type LedgerSECP256K1Mock struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mock LedgerSECP256K1Mock) Close() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mock LedgerSECP256K1Mock) GetPublicKeySECP256K1(derivationPath []uint32) ([]byte, error) {
|
||||||
|
if derivationPath[0] != 44 {
|
||||||
|
return nil, errors.New("Invalid derivation path")
|
||||||
|
}
|
||||||
|
if derivationPath[1] != 118 {
|
||||||
|
return nil, errors.New("Invalid derivation path")
|
||||||
|
}
|
||||||
|
|
||||||
|
seed, err := bip39.NewSeedWithErrorChecking(tests.TestMnemonic, "")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
path := hd.NewParams(derivationPath[0], derivationPath[1], derivationPath[2], derivationPath[3] != 0, derivationPath[4])
|
||||||
|
masterPriv, ch := hd.ComputeMastersFromSeed(seed)
|
||||||
|
derivedPriv, err := hd.DerivePrivateKeyForPath(masterPriv, ch, path.String())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, pubkeyObject := secp256k1.PrivKeyFromBytes(secp256k1.S256(), derivedPriv[:])
|
||||||
|
|
||||||
|
return pubkeyObject.SerializeUncompressed(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mock LedgerSECP256K1Mock) SignSECP256K1(derivationPath []uint32, message []byte) ([]byte, error) {
|
||||||
|
path := hd.NewParams(derivationPath[0], derivationPath[1], derivationPath[2], derivationPath[3] != 0, derivationPath[4])
|
||||||
|
seed, err := bip39.NewSeedWithErrorChecking(tests.TestMnemonic, "")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
masterPriv, ch := hd.ComputeMastersFromSeed(seed)
|
||||||
|
derivedPriv, err := hd.DerivePrivateKeyForPath(masterPriv, ch, path.String())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
priv, _ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), derivedPriv[:])
|
||||||
|
|
||||||
|
sig, err := priv.Sign(crypto.Sha256(message))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Need to return DER as the ledger does
|
||||||
|
sig2 := btcec.Signature{R: sig.R, S: sig.S}
|
||||||
|
return sig2.Serialize(), nil
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
// +build !cgo !ledger
|
||||||
|
// test_ledger_mock
|
||||||
|
|
||||||
|
package crypto
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// If ledger support (build tag) has been enabled, which implies a CGO dependency,
|
||||||
|
// set the discoverLedger function which is responsible for loading the Ledger
|
||||||
|
// device at runtime or returning an error.
|
||||||
|
func init() {
|
||||||
|
discoverLedger = func() (LedgerSECP256K1, error) {
|
||||||
|
return nil, errors.New("support for ledger devices is not available in this executable")
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,10 +1,8 @@
|
||||||
// +build cgo,ledger
|
// +build cgo,ledger,!test_ledger_mock
|
||||||
|
|
||||||
package crypto
|
package crypto
|
||||||
|
|
||||||
import (
|
import ledger "github.com/zondax/ledger-cosmos-go"
|
||||||
ledger "github.com/zondax/ledger-cosmos-go"
|
|
||||||
)
|
|
||||||
|
|
||||||
// If ledger support (build tag) has been enabled, which implies a CGO dependency,
|
// If ledger support (build tag) has been enabled, which implies a CGO dependency,
|
||||||
// set the discoverLedger function which is responsible for loading the Ledger
|
// set the discoverLedger function which is responsible for loading the Ledger
|
|
@ -45,9 +45,6 @@ type (
|
||||||
|
|
||||||
// NewPrivKeyLedgerSecp256k1 will generate a new key and store the public key
|
// NewPrivKeyLedgerSecp256k1 will generate a new key and store the public key
|
||||||
// for later use.
|
// for later use.
|
||||||
//
|
|
||||||
// CONTRACT: The ledger device, ledgerDevice, must be loaded and set prior to
|
|
||||||
// any creation of a PrivKeyLedgerSecp256k1.
|
|
||||||
func NewPrivKeyLedgerSecp256k1(path hd.BIP44Params) (tmcrypto.PrivKey, error) {
|
func NewPrivKeyLedgerSecp256k1(path hd.BIP44Params) (tmcrypto.PrivKey, error) {
|
||||||
device, err := getLedgerDevice()
|
device, err := getLedgerDevice()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -103,8 +100,8 @@ func (pkl PrivKeyLedgerSecp256k1) Bytes() []byte {
|
||||||
// Equals implements the PrivKey interface. It makes sure two private keys
|
// Equals implements the PrivKey interface. It makes sure two private keys
|
||||||
// refer to the same public key.
|
// refer to the same public key.
|
||||||
func (pkl PrivKeyLedgerSecp256k1) Equals(other tmcrypto.PrivKey) bool {
|
func (pkl PrivKeyLedgerSecp256k1) Equals(other tmcrypto.PrivKey) bool {
|
||||||
if ledger, ok := other.(*PrivKeyLedgerSecp256k1); ok {
|
if otherKey, ok := other.(PrivKeyLedgerSecp256k1); ok {
|
||||||
return pkl.CachedPubKey.Equals(ledger.CachedPubKey)
|
return pkl.CachedPubKey.Equals(otherKey.CachedPubKey)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,19 @@
|
||||||
package crypto
|
package crypto
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/tests"
|
||||||
|
|
||||||
|
tmcrypto "github.com/tendermint/tendermint/crypto"
|
||||||
|
"github.com/tendermint/tendermint/crypto/encoding/amino"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/crypto/keys/hd"
|
"github.com/cosmos/cosmos-sdk/crypto/keys/hd"
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
// This tests assume a ledger is not plugged in
|
|
||||||
func TestLedgerErrorHandling(t *testing.T) {
|
func TestLedgerErrorHandling(t *testing.T) {
|
||||||
// first, try to generate a key, must return an error
|
// first, try to generate a key, must return an error
|
||||||
// (no panic)
|
// (no panic)
|
||||||
|
@ -15,3 +21,135 @@ func TestLedgerErrorHandling(t *testing.T) {
|
||||||
_, err := NewPrivKeyLedgerSecp256k1(path)
|
_, err := NewPrivKeyLedgerSecp256k1(path)
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPublicKey(t *testing.T) {
|
||||||
|
path := *hd.NewFundraiserParams(0, 0)
|
||||||
|
priv, err := NewPrivKeyLedgerSecp256k1(path)
|
||||||
|
require.Nil(t, err, "%s", err)
|
||||||
|
require.NotNil(t, priv)
|
||||||
|
|
||||||
|
pubKeyAddr, err := sdk.Bech32ifyAccPub(priv.PubKey())
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, "cosmospub1addwnpepqd87l8xhcnrrtzxnkql7k55ph8fr9jarf4hn6udwukfprlalu8lgw0urza0",
|
||||||
|
pubKeyAddr, "Is your device using test mnemonic: %s ?", tests.TestMnemonic)
|
||||||
|
|
||||||
|
require.Equal(t, "5075624b6579536563703235366b317b303334464546394344374334433633353838443342303"+
|
||||||
|
"3464542353238314239443233324342413334443646334437314145453539323131464642464531464538377d",
|
||||||
|
fmt.Sprintf("%x", priv.PubKey()))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPublicKeyHDPath(t *testing.T) {
|
||||||
|
expectedAnswers := []string{
|
||||||
|
"cosmospub1addwnpepqd87l8xhcnrrtzxnkql7k55ph8fr9jarf4hn6udwukfprlalu8lgw0urza0",
|
||||||
|
"cosmospub1addwnpepqfsdqjr68h7wjg5wacksmqaypasnra232fkgu5sxdlnlu8j22ztxvlqvd65",
|
||||||
|
"cosmospub1addwnpepqw3xwqun6q43vtgw6p4qspq7srvxhcmvq4jrx5j5ma6xy3r7k6dtxmrkh3d",
|
||||||
|
"cosmospub1addwnpepqvez9lrp09g8w7gkv42y4yr5p6826cu28ydrhrujv862yf4njmqyyjr4pjs",
|
||||||
|
"cosmospub1addwnpepq06hw3enfrtmq8n67teytcmtnrgcr0yntmyt25kdukfjkerdc7lqg32rcz7",
|
||||||
|
"cosmospub1addwnpepqg3trf2gd0s2940nckrxherwqhgmm6xd5h4pcnrh4x7y35h6yafmcpk5qns",
|
||||||
|
"cosmospub1addwnpepqdm6rjpx6wsref8wjn7ym6ntejet430j4szpngfgc20caz83lu545vuv8hp",
|
||||||
|
"cosmospub1addwnpepqvdhtjzy2wf44dm03jxsketxc07vzqwvt3vawqqtljgsr9s7jvydjmt66ew",
|
||||||
|
"cosmospub1addwnpepqwystfpyxwcava7v3t7ndps5xzu6s553wxcxzmmnxevlzvwrlqpzz695nw9",
|
||||||
|
"cosmospub1addwnpepqw970u6gjqkccg9u3rfj99857wupj2z9fqfzy2w7e5dd7xn7kzzgkgqch0r",
|
||||||
|
}
|
||||||
|
|
||||||
|
const numIters = 10
|
||||||
|
|
||||||
|
privKeys := make([]tmcrypto.PrivKey, numIters)
|
||||||
|
|
||||||
|
// Check with device
|
||||||
|
for i := uint32(0); i < 10; i++ {
|
||||||
|
path := *hd.NewFundraiserParams(0, i)
|
||||||
|
fmt.Printf("Checking keys at %v\n", path)
|
||||||
|
|
||||||
|
priv, err := NewPrivKeyLedgerSecp256k1(path)
|
||||||
|
require.Nil(t, err, "%s", err)
|
||||||
|
require.NotNil(t, priv)
|
||||||
|
|
||||||
|
// Check other methods
|
||||||
|
require.NoError(t, priv.(PrivKeyLedgerSecp256k1).ValidateKey())
|
||||||
|
tmp := priv.(PrivKeyLedgerSecp256k1)
|
||||||
|
(&tmp).AssertIsPrivKeyInner()
|
||||||
|
|
||||||
|
pubKeyAddr, err := sdk.Bech32ifyAccPub(priv.PubKey())
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t,
|
||||||
|
expectedAnswers[i], pubKeyAddr,
|
||||||
|
"Is your device using test mnemonic: %s ?", tests.TestMnemonic)
|
||||||
|
|
||||||
|
// Store and restore
|
||||||
|
serializedPk := priv.Bytes()
|
||||||
|
require.NotNil(t, serializedPk)
|
||||||
|
require.Equal(t, 44, len(serializedPk))
|
||||||
|
|
||||||
|
privKeys[i] = priv
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now check equality
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
for j := 0; j < 10; j++ {
|
||||||
|
require.Equal(t, i == j, privKeys[i].Equals(privKeys[j]))
|
||||||
|
require.Equal(t, i == j, privKeys[j].Equals(privKeys[i]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getFakeTx(accountNumber uint32) []byte {
|
||||||
|
tmp := fmt.Sprintf(
|
||||||
|
`{"account_number":"%d","chain_id":"1234","fee":{"amount":[{"amount":"150","denom":"atom"}],"gas":"5000"},"memo":"memo","msgs":[[""]],"sequence":"6"}`,
|
||||||
|
accountNumber)
|
||||||
|
|
||||||
|
return []byte(tmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSignaturesHD(t *testing.T) {
|
||||||
|
for account := uint32(0); account < 100; account += 30 {
|
||||||
|
msg := getFakeTx(account)
|
||||||
|
|
||||||
|
path := *hd.NewFundraiserParams(account, account/5)
|
||||||
|
fmt.Printf("Checking signature at %v --- PLEASE REVIEW AND ACCEPT IN THE DEVICE\n", path)
|
||||||
|
|
||||||
|
priv, err := NewPrivKeyLedgerSecp256k1(path)
|
||||||
|
require.Nil(t, err, "%s", err)
|
||||||
|
|
||||||
|
pub := priv.PubKey()
|
||||||
|
sig, err := priv.Sign(msg)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
valid := pub.VerifyBytes(msg, sig)
|
||||||
|
require.True(t, valid, "Is your device using test mnemonic: %s ?", tests.TestMnemonic)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRealLedgerSecp256k1(t *testing.T) {
|
||||||
|
msg := getFakeTx(50)
|
||||||
|
path := *hd.NewFundraiserParams(0, 0)
|
||||||
|
priv, err := NewPrivKeyLedgerSecp256k1(path)
|
||||||
|
require.Nil(t, err, "%s", err)
|
||||||
|
|
||||||
|
pub := priv.PubKey()
|
||||||
|
sig, err := priv.Sign(msg)
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
valid := pub.VerifyBytes(msg, sig)
|
||||||
|
require.True(t, valid)
|
||||||
|
|
||||||
|
// now, let's serialize the public key and make sure it still works
|
||||||
|
bs := priv.PubKey().Bytes()
|
||||||
|
pub2, err := cryptoAmino.PubKeyFromBytes(bs)
|
||||||
|
require.Nil(t, err, "%+v", err)
|
||||||
|
|
||||||
|
// make sure we get the same pubkey when we load from disk
|
||||||
|
require.Equal(t, pub, pub2)
|
||||||
|
|
||||||
|
// signing with the loaded key should match the original pubkey
|
||||||
|
sig, err = priv.Sign(msg)
|
||||||
|
require.Nil(t, err)
|
||||||
|
valid = pub.VerifyBytes(msg, sig)
|
||||||
|
require.True(t, valid)
|
||||||
|
|
||||||
|
// make sure pubkeys serialize properly as well
|
||||||
|
bs = pub.Bytes()
|
||||||
|
bpub, err := cryptoAmino.PubKeyFromBytes(bs)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, pub, bpub)
|
||||||
|
}
|
||||||
|
|
|
@ -120,7 +120,7 @@ func interceptLoadConfig() (conf *cfg.Config, err error) {
|
||||||
|
|
||||||
// validate the config with the sdk's requirements.
|
// validate the config with the sdk's requirements.
|
||||||
func validateConfig(conf *cfg.Config) error {
|
func validateConfig(conf *cfg.Config) error {
|
||||||
if conf.Consensus.CreateEmptyBlocks == false {
|
if !conf.Consensus.CreateEmptyBlocks {
|
||||||
return errors.New("config option CreateEmptyBlocks = false is currently unsupported")
|
return errors.New("config option CreateEmptyBlocks = false is currently unsupported")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -293,7 +293,7 @@ func newIAVLIterator(tree *iavl.ImmutableTree, start, end []byte, ascending bool
|
||||||
start: types.Cp(start),
|
start: types.Cp(start),
|
||||||
end: types.Cp(end),
|
end: types.Cp(end),
|
||||||
ascending: ascending,
|
ascending: ascending,
|
||||||
iterCh: make(chan cmn.KVPair, 0), // Set capacity > 0?
|
iterCh: make(chan cmn.KVPair), // Set capacity > 0?
|
||||||
quitCh: make(chan struct{}),
|
quitCh: make(chan struct{}),
|
||||||
initCh: make(chan struct{}),
|
initCh: make(chan struct{}),
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,16 @@
|
||||||
package prefix
|
package prefix
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math/rand"
|
"crypto/rand"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
|
|
||||||
tiavl "github.com/tendermint/iavl"
|
|
||||||
dbm "github.com/tendermint/tendermint/libs/db"
|
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/store/dbadapter"
|
"github.com/cosmos/cosmos-sdk/store/dbadapter"
|
||||||
"github.com/cosmos/cosmos-sdk/store/gaskv"
|
"github.com/cosmos/cosmos-sdk/store/gaskv"
|
||||||
"github.com/cosmos/cosmos-sdk/store/iavl"
|
"github.com/cosmos/cosmos-sdk/store/iavl"
|
||||||
"github.com/cosmos/cosmos-sdk/store/types"
|
"github.com/cosmos/cosmos-sdk/store/types"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
tiavl "github.com/tendermint/iavl"
|
||||||
|
dbm "github.com/tendermint/tendermint/libs/db"
|
||||||
)
|
)
|
||||||
|
|
||||||
// copied from iavl/store_test.go
|
// copied from iavl/store_test.go
|
||||||
|
|
|
@ -33,11 +33,7 @@ func RequireProof(subpath string) bool {
|
||||||
// Currently, only when query subpath is "/key", will proof be included in
|
// Currently, only when query subpath is "/key", will proof be included in
|
||||||
// response. If there are some changes about proof building in iavlstore.go,
|
// response. If there are some changes about proof building in iavlstore.go,
|
||||||
// we must change code here to keep consistency with iavlStore#Query.
|
// we must change code here to keep consistency with iavlStore#Query.
|
||||||
if subpath == "/key" {
|
return subpath == "/key"
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
package tests
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Tests expect a ledger device initialized to the following mnemonic
|
||||||
|
TestMnemonic = "equip will roof matter pink blind book anxiety banner elbow sun young"
|
||||||
|
)
|
|
@ -5,8 +5,8 @@ PKGS=$(go list ./... | grep -v /vendor/ | grep -v github.com/cosmos/cosmos-sdk/c
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
echo "mode: atomic" > coverage.txt
|
echo "mode: atomic" > coverage.txt
|
||||||
for pkg in ${PKGS}; do
|
for pkg in ${PKGS[@]}; do
|
||||||
go test -v -timeout 30m -race -coverprofile=profile.out -covermode=atomic "$pkg"
|
go test -v -timeout 30m -race -coverprofile=profile.out -covermode=atomic -tags='ledger test_ledger_mock' "$pkg"
|
||||||
if [ -f profile.out ]; then
|
if [ -f profile.out ]; then
|
||||||
tail -n +2 profile.out >> coverage.txt;
|
tail -n +2 profile.out >> coverage.txt;
|
||||||
rm profile.out
|
rm profile.out
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -201,3 +202,21 @@ var cdc = amino.NewCodec()
|
||||||
func init() {
|
func init() {
|
||||||
ctypes.RegisterAmino(cdc)
|
ctypes.RegisterAmino(cdc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetTempDir creates a temporary directory and returns a clean up function
|
||||||
|
// to be deferred
|
||||||
|
func GetTempDir(prefix string) (string, func(), error) {
|
||||||
|
rootDir, err := ioutil.TempDir("", prefix)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanUp := func() {
|
||||||
|
err := os.RemoveAll(rootDir)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rootDir, cleanUp, nil
|
||||||
|
}
|
||||||
|
|
|
@ -86,7 +86,7 @@ func (aa AccAddress) Equals(aa2 Address) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return bytes.Compare(aa.Bytes(), aa2.Bytes()) == 0
|
return bytes.Equal(aa.Bytes(), aa2.Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns boolean for whether an AccAddress is empty
|
// Returns boolean for whether an AccAddress is empty
|
||||||
|
@ -96,7 +96,7 @@ func (aa AccAddress) Empty() bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
aa2 := AccAddress{}
|
aa2 := AccAddress{}
|
||||||
return bytes.Compare(aa.Bytes(), aa2.Bytes()) == 0
|
return bytes.Equal(aa.Bytes(), aa2.Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Marshal returns the raw address bytes. It is needed for protobuf
|
// Marshal returns the raw address bytes. It is needed for protobuf
|
||||||
|
@ -155,7 +155,7 @@ func (aa AccAddress) String() string {
|
||||||
func (aa AccAddress) Format(s fmt.State, verb rune) {
|
func (aa AccAddress) Format(s fmt.State, verb rune) {
|
||||||
switch verb {
|
switch verb {
|
||||||
case 's':
|
case 's':
|
||||||
s.Write([]byte(fmt.Sprintf("%s", aa.String())))
|
s.Write([]byte(aa.String()))
|
||||||
case 'p':
|
case 'p':
|
||||||
s.Write([]byte(fmt.Sprintf("%p", aa)))
|
s.Write([]byte(fmt.Sprintf("%p", aa)))
|
||||||
default:
|
default:
|
||||||
|
@ -202,7 +202,7 @@ func (va ValAddress) Equals(va2 Address) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return bytes.Compare(va.Bytes(), va2.Bytes()) == 0
|
return bytes.Equal(va.Bytes(), va2.Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns boolean for whether an AccAddress is empty
|
// Returns boolean for whether an AccAddress is empty
|
||||||
|
@ -212,7 +212,7 @@ func (va ValAddress) Empty() bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
va2 := ValAddress{}
|
va2 := ValAddress{}
|
||||||
return bytes.Compare(va.Bytes(), va2.Bytes()) == 0
|
return bytes.Equal(va.Bytes(), va2.Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Marshal returns the raw address bytes. It is needed for protobuf
|
// Marshal returns the raw address bytes. It is needed for protobuf
|
||||||
|
@ -272,7 +272,7 @@ func (va ValAddress) String() string {
|
||||||
func (va ValAddress) Format(s fmt.State, verb rune) {
|
func (va ValAddress) Format(s fmt.State, verb rune) {
|
||||||
switch verb {
|
switch verb {
|
||||||
case 's':
|
case 's':
|
||||||
s.Write([]byte(fmt.Sprintf("%s", va.String())))
|
s.Write([]byte(va.String()))
|
||||||
case 'p':
|
case 'p':
|
||||||
s.Write([]byte(fmt.Sprintf("%p", va)))
|
s.Write([]byte(fmt.Sprintf("%p", va)))
|
||||||
default:
|
default:
|
||||||
|
@ -324,7 +324,7 @@ func (ca ConsAddress) Equals(ca2 Address) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return bytes.Compare(ca.Bytes(), ca2.Bytes()) == 0
|
return bytes.Equal(ca.Bytes(), ca2.Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns boolean for whether an ConsAddress is empty
|
// Returns boolean for whether an ConsAddress is empty
|
||||||
|
@ -334,7 +334,7 @@ func (ca ConsAddress) Empty() bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
ca2 := ConsAddress{}
|
ca2 := ConsAddress{}
|
||||||
return bytes.Compare(ca.Bytes(), ca2.Bytes()) == 0
|
return bytes.Equal(ca.Bytes(), ca2.Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Marshal returns the raw address bytes. It is needed for protobuf
|
// Marshal returns the raw address bytes. It is needed for protobuf
|
||||||
|
@ -394,7 +394,7 @@ func (ca ConsAddress) String() string {
|
||||||
func (ca ConsAddress) Format(s fmt.State, verb rune) {
|
func (ca ConsAddress) Format(s fmt.State, verb rune) {
|
||||||
switch verb {
|
switch verb {
|
||||||
case 's':
|
case 's':
|
||||||
s.Write([]byte(fmt.Sprintf("%s", ca.String())))
|
s.Write([]byte(ca.String()))
|
||||||
case 'p':
|
case 'p':
|
||||||
s.Write([]byte(fmt.Sprintf("%p", ca)))
|
s.Write([]byte(fmt.Sprintf("%p", ca)))
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -5,13 +5,11 @@ import (
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
|
|
||||||
"github.com/tendermint/tendermint/crypto/ed25519"
|
|
||||||
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/types"
|
"github.com/cosmos/cosmos-sdk/types"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"github.com/tendermint/tendermint/crypto/ed25519"
|
||||||
)
|
)
|
||||||
|
|
||||||
var invalidStrs = []string{
|
var invalidStrs = []string{
|
||||||
|
|
|
@ -19,10 +19,7 @@ type CodespaceType string
|
||||||
|
|
||||||
// IsOK - is everything okay?
|
// IsOK - is everything okay?
|
||||||
func (code CodeType) IsOK() bool {
|
func (code CodeType) IsOK() bool {
|
||||||
if code == CodeOK {
|
return code == CodeOK
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SDK error codes
|
// SDK error codes
|
||||||
|
|
|
@ -30,8 +30,7 @@ func TestCommitID(t *testing.T) {
|
||||||
var empty CommitID
|
var empty CommitID
|
||||||
require.True(t, empty.IsZero())
|
require.True(t, empty.IsZero())
|
||||||
|
|
||||||
var nonempty CommitID
|
var nonempty = CommitID{
|
||||||
nonempty = CommitID{
|
|
||||||
Version: 1,
|
Version: 1,
|
||||||
Hash: []byte("testhash"),
|
Hash: []byte("testhash"),
|
||||||
}
|
}
|
||||||
|
|
|
@ -164,7 +164,7 @@ func (vo VoteOption) String() string {
|
||||||
func (vo VoteOption) Format(s fmt.State, verb rune) {
|
func (vo VoteOption) Format(s fmt.State, verb rune) {
|
||||||
switch verb {
|
switch verb {
|
||||||
case 's':
|
case 's':
|
||||||
s.Write([]byte(fmt.Sprintf("%s", vo.String())))
|
s.Write([]byte(vo.String()))
|
||||||
default:
|
default:
|
||||||
s.Write([]byte(fmt.Sprintf("%v", byte(vo))))
|
s.Write([]byte(fmt.Sprintf("%v", byte(vo))))
|
||||||
}
|
}
|
||||||
|
|
|
@ -238,7 +238,7 @@ func GenTx(msgs []sdk.Msg, accnums []uint64, seq []uint64, priv ...crypto.PrivKe
|
||||||
// GeneratePrivKeys generates a total n Ed25519 private keys.
|
// GeneratePrivKeys generates a total n Ed25519 private keys.
|
||||||
func GeneratePrivKeys(n int) (keys []crypto.PrivKey) {
|
func GeneratePrivKeys(n int) (keys []crypto.PrivKey) {
|
||||||
// TODO: Randomize this between ed25519 and secp256k1
|
// TODO: Randomize this between ed25519 and secp256k1
|
||||||
keys = make([]crypto.PrivKey, n, n)
|
keys = make([]crypto.PrivKey, n)
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
keys[i] = ed25519.GenPrivKey()
|
keys[i] = ed25519.GenPrivKey()
|
||||||
}
|
}
|
||||||
|
@ -249,8 +249,8 @@ func GeneratePrivKeys(n int) (keys []crypto.PrivKey) {
|
||||||
// GeneratePrivKeyAddressPairs generates a total of n private key, address
|
// GeneratePrivKeyAddressPairs generates a total of n private key, address
|
||||||
// pairs.
|
// pairs.
|
||||||
func GeneratePrivKeyAddressPairs(n int) (keys []crypto.PrivKey, addrs []sdk.AccAddress) {
|
func GeneratePrivKeyAddressPairs(n int) (keys []crypto.PrivKey, addrs []sdk.AccAddress) {
|
||||||
keys = make([]crypto.PrivKey, n, n)
|
keys = make([]crypto.PrivKey, n)
|
||||||
addrs = make([]sdk.AccAddress, n, n)
|
addrs = make([]sdk.AccAddress, n)
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
if rand.Int63()%2 == 0 {
|
if rand.Int63()%2 == 0 {
|
||||||
keys[i] = secp256k1.GenPrivKey()
|
keys[i] = secp256k1.GenPrivKey()
|
||||||
|
@ -265,8 +265,8 @@ func GeneratePrivKeyAddressPairs(n int) (keys []crypto.PrivKey, addrs []sdk.AccA
|
||||||
// GeneratePrivKeyAddressPairsFromRand generates a total of n private key, address
|
// GeneratePrivKeyAddressPairsFromRand generates a total of n private key, address
|
||||||
// pairs using the provided randomness source.
|
// pairs using the provided randomness source.
|
||||||
func GeneratePrivKeyAddressPairsFromRand(rand *rand.Rand, n int) (keys []crypto.PrivKey, addrs []sdk.AccAddress) {
|
func GeneratePrivKeyAddressPairsFromRand(rand *rand.Rand, n int) (keys []crypto.PrivKey, addrs []sdk.AccAddress) {
|
||||||
keys = make([]crypto.PrivKey, n, n)
|
keys = make([]crypto.PrivKey, n)
|
||||||
addrs = make([]sdk.AccAddress, n, n)
|
addrs = make([]sdk.AccAddress, n)
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
secret := make([]byte, 32)
|
secret := make([]byte, 32)
|
||||||
_, err := rand.Read(secret)
|
_, err := rand.Read(secret)
|
||||||
|
@ -287,7 +287,7 @@ func GeneratePrivKeyAddressPairsFromRand(rand *rand.Rand, n int) (keys []crypto.
|
||||||
// provided addresses and coin denominations.
|
// provided addresses and coin denominations.
|
||||||
// nolint: errcheck
|
// nolint: errcheck
|
||||||
func RandomSetGenesis(r *rand.Rand, app *App, addrs []sdk.AccAddress, denoms []string) {
|
func RandomSetGenesis(r *rand.Rand, app *App, addrs []sdk.AccAddress, denoms []string) {
|
||||||
accts := make([]auth.Account, len(addrs), len(addrs))
|
accts := make([]auth.Account, len(addrs))
|
||||||
randCoinIntervals := []BigInterval{
|
randCoinIntervals := []BigInterval{
|
||||||
{sdk.NewIntWithDecimal(1, 0), sdk.NewIntWithDecimal(1, 1)},
|
{sdk.NewIntWithDecimal(1, 0), sdk.NewIntWithDecimal(1, 1)},
|
||||||
{sdk.NewIntWithDecimal(1, 2), sdk.NewIntWithDecimal(1, 3)},
|
{sdk.NewIntWithDecimal(1, 2), sdk.NewIntWithDecimal(1, 3)},
|
||||||
|
@ -295,7 +295,7 @@ func RandomSetGenesis(r *rand.Rand, app *App, addrs []sdk.AccAddress, denoms []s
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < len(accts); i++ {
|
for i := 0; i < len(accts); i++ {
|
||||||
coins := make([]sdk.Coin, len(denoms), len(denoms))
|
coins := make([]sdk.Coin, len(denoms))
|
||||||
|
|
||||||
// generate a random coin for each denomination
|
// generate a random coin for each denomination
|
||||||
for j := 0; j < len(denoms); j++ {
|
for j := 0; j < len(denoms); j++ {
|
||||||
|
@ -328,7 +328,7 @@ func GetAllAccounts(mapper auth.AccountKeeper, ctx sdk.Context) []auth.Account {
|
||||||
// that they differ only by having the sequence numbers incremented between
|
// that they differ only by having the sequence numbers incremented between
|
||||||
// every transaction.
|
// every transaction.
|
||||||
func GenSequenceOfTxs(msgs []sdk.Msg, accnums []uint64, initSeqNums []uint64, numToGenerate int, priv ...crypto.PrivKey) []auth.StdTx {
|
func GenSequenceOfTxs(msgs []sdk.Msg, accnums []uint64, initSeqNums []uint64, numToGenerate int, priv ...crypto.PrivKey) []auth.StdTx {
|
||||||
txs := make([]auth.StdTx, numToGenerate, numToGenerate)
|
txs := make([]auth.StdTx, numToGenerate)
|
||||||
for i := 0; i < numToGenerate; i++ {
|
for i := 0; i < numToGenerate; i++ {
|
||||||
txs[i] = GenTx(msgs, accnums, initSeqNums, priv...)
|
txs[i] = GenTx(msgs, accnums, initSeqNums, priv...)
|
||||||
incrementAllSequenceNumbers(initSeqNums)
|
incrementAllSequenceNumbers(initSeqNums)
|
||||||
|
|
|
@ -222,7 +222,7 @@ func (k Keeper) InsertUBDQueue(ctx sdk.Context, ubd types.UnbondingDelegation,
|
||||||
completionTime time.Time) {
|
completionTime time.Time) {
|
||||||
|
|
||||||
timeSlice := k.GetUBDQueueTimeSlice(ctx, completionTime)
|
timeSlice := k.GetUBDQueueTimeSlice(ctx, completionTime)
|
||||||
dvPair := types.DVPair{ubd.DelegatorAddr, ubd.ValidatorAddr}
|
dvPair := types.DVPair{DelegatorAddr: ubd.DelegatorAddr, ValidatorAddr: ubd.ValidatorAddr}
|
||||||
if len(timeSlice) == 0 {
|
if len(timeSlice) == 0 {
|
||||||
k.SetUBDQueueTimeSlice(ctx, completionTime, []types.DVPair{dvPair})
|
k.SetUBDQueueTimeSlice(ctx, completionTime, []types.DVPair{dvPair})
|
||||||
} else {
|
} else {
|
||||||
|
@ -314,10 +314,7 @@ func (k Keeper) HasReceivingRedelegation(ctx sdk.Context,
|
||||||
iterator := sdk.KVStorePrefixIterator(store, prefix)
|
iterator := sdk.KVStorePrefixIterator(store, prefix)
|
||||||
defer iterator.Close()
|
defer iterator.Close()
|
||||||
|
|
||||||
if iterator.Valid() {
|
return iterator.Valid()
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasMaxRedelegationEntries - redelegation has maximum number of entries
|
// HasMaxRedelegationEntries - redelegation has maximum number of entries
|
||||||
|
@ -411,7 +408,11 @@ func (k Keeper) InsertRedelegationQueue(ctx sdk.Context, red types.Redelegation,
|
||||||
completionTime time.Time) {
|
completionTime time.Time) {
|
||||||
|
|
||||||
timeSlice := k.GetRedelegationQueueTimeSlice(ctx, completionTime)
|
timeSlice := k.GetRedelegationQueueTimeSlice(ctx, completionTime)
|
||||||
dvvTriplet := types.DVVTriplet{red.DelegatorAddr, red.ValidatorSrcAddr, red.ValidatorDstAddr}
|
dvvTriplet := types.DVVTriplet{
|
||||||
|
DelegatorAddr: red.DelegatorAddr,
|
||||||
|
ValidatorSrcAddr: red.ValidatorSrcAddr,
|
||||||
|
ValidatorDstAddr: red.ValidatorDstAddr}
|
||||||
|
|
||||||
if len(timeSlice) == 0 {
|
if len(timeSlice) == 0 {
|
||||||
k.SetRedelegationQueueTimeSlice(ctx, completionTime, []types.DVVTriplet{dvvTriplet})
|
k.SetRedelegationQueueTimeSlice(ctx, completionTime, []types.DVVTriplet{dvvTriplet})
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -166,7 +166,7 @@ func TestAddr(addr string, bech string) sdk.AccAddress {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
if bytes.Compare(bechres, res) != 0 {
|
if !bytes.Equal(bechres, res) {
|
||||||
panic("Bech decode and hex decode don't match")
|
panic("Bech decode and hex decode don't match")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,10 @@ import (
|
||||||
"github.com/cosmos/cosmos-sdk/x/staking/keeper"
|
"github.com/cosmos/cosmos-sdk/x/staking/keeper"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
noOperation = "no-operation"
|
||||||
|
)
|
||||||
|
|
||||||
// SimulateMsgCreateValidator
|
// SimulateMsgCreateValidator
|
||||||
func SimulateMsgCreateValidator(m auth.AccountKeeper, k staking.Keeper) simulation.Operation {
|
func SimulateMsgCreateValidator(m auth.AccountKeeper, k staking.Keeper) simulation.Operation {
|
||||||
handler := staking.NewHandler(k)
|
handler := staking.NewHandler(k)
|
||||||
|
@ -39,7 +43,7 @@ func SimulateMsgCreateValidator(m auth.AccountKeeper, k staking.Keeper) simulati
|
||||||
}
|
}
|
||||||
|
|
||||||
if amount.Equal(sdk.ZeroInt()) {
|
if amount.Equal(sdk.ZeroInt()) {
|
||||||
return "no-operation", nil, nil
|
return noOperation, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
selfDelegation := sdk.NewCoin(denom, amount)
|
selfDelegation := sdk.NewCoin(denom, amount)
|
||||||
|
@ -146,13 +150,13 @@ func SimulateMsgUndelegate(m auth.AccountKeeper, k staking.Keeper) simulation.Op
|
||||||
delegatorAddress := delegatorAcc.Address
|
delegatorAddress := delegatorAcc.Address
|
||||||
delegations := k.GetAllDelegatorDelegations(ctx, delegatorAddress)
|
delegations := k.GetAllDelegatorDelegations(ctx, delegatorAddress)
|
||||||
if len(delegations) == 0 {
|
if len(delegations) == 0 {
|
||||||
return "no-operation", nil, nil
|
return noOperation, nil, nil
|
||||||
}
|
}
|
||||||
delegation := delegations[r.Intn(len(delegations))]
|
delegation := delegations[r.Intn(len(delegations))]
|
||||||
|
|
||||||
numShares := simulation.RandomDecAmount(r, delegation.Shares)
|
numShares := simulation.RandomDecAmount(r, delegation.Shares)
|
||||||
if numShares.Equal(sdk.ZeroDec()) {
|
if numShares.Equal(sdk.ZeroDec()) {
|
||||||
return "no-operation", nil, nil
|
return noOperation, nil, nil
|
||||||
}
|
}
|
||||||
msg := staking.MsgUndelegate{
|
msg := staking.MsgUndelegate{
|
||||||
DelegatorAddr: delegatorAddress,
|
DelegatorAddr: delegatorAddress,
|
||||||
|
@ -194,7 +198,7 @@ func SimulateMsgBeginRedelegate(m auth.AccountKeeper, k staking.Keeper) simulati
|
||||||
amount = simulation.RandomAmount(r, amount)
|
amount = simulation.RandomAmount(r, amount)
|
||||||
}
|
}
|
||||||
if amount.Equal(sdk.ZeroInt()) {
|
if amount.Equal(sdk.ZeroInt()) {
|
||||||
return "no-operation", nil, nil
|
return noOperation, nil, nil
|
||||||
}
|
}
|
||||||
msg := staking.MsgBeginRedelegate{
|
msg := staking.MsgBeginRedelegate{
|
||||||
DelegatorAddr: delegatorAddress,
|
DelegatorAddr: delegatorAddress,
|
||||||
|
|
Loading…
Reference in New Issue