From 97d96612c9cf1c05475313a4b6fe5cffdfe34a23 Mon Sep 17 00:00:00 2001 From: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Date: Wed, 18 Nov 2020 19:42:45 +0100 Subject: [PATCH] crypto/hd: add 'm/' prefix to hd path (#7970) * crypto/hd: add 'm/' prefix to hd path * update fundraiser path * fix some tests * tests * fix test case * changelog * fix ledger tests --- CHANGELOG.md | 4 + crypto/hd/fundraiser_test.go | 5 +- crypto/hd/hdpath.go | 50 +++++-- crypto/hd/hdpath_test.go | 187 ++++++++++++++------------ crypto/keyring/keyring_ledger_test.go | 4 +- crypto/keyring/types_test.go | 26 ++-- crypto/ledger/ledger_test.go | 24 ++-- types/address.go | 10 +- 8 files changed, 172 insertions(+), 138 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 46d8a76ef3..efca4d9bd3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,10 @@ Ref: https://keepachangelog.com/en/1.0.0/ * Updated iavl dependency to v0.15-rc2 * (version) [\#7848](https://github.com/cosmos/cosmos-sdk/pull/7848) [\#7941](https://github.com/cosmos/cosmos-sdk/pull/7941) `version --long` output now shows the list of build dependencies and replaced build dependencies. +### Bug Fixes + +* (crypto) [\#7966](https://github.com/cosmos/cosmos-sdk/issues/7966) `Bip44Params` `String()` function now correctly returns the absolute HD path by adding the `m/` prefix. + ## [v0.40.0-rc3](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.40.0-rc3) - 2020-11-06 ### Client Breaking diff --git a/crypto/hd/fundraiser_test.go b/crypto/hd/fundraiser_test.go index e8649a0086..4afbfc5a9c 100644 --- a/crypto/hd/fundraiser_test.go +++ b/crypto/hd/fundraiser_test.go @@ -27,7 +27,7 @@ type addrData struct { } func TestFullFundraiserPath(t *testing.T) { - require.Equal(t, "44'/118'/0'/0/0", hd.NewFundraiserParams(0, 118, 0).String()) + require.Equal(t, "m/44'/118'/0'/0/0", hd.NewFundraiserParams(0, 118, 0).String()) } func initFundraiserTestVectors(t *testing.T) []addrData { @@ -63,8 +63,9 @@ func TestFundraiserCompatibility(t *testing.T) { t.Logf("ROUND: %d MNEMONIC: %s", i, d.Mnemonic) master, ch := hd.ComputeMastersFromSeed(seed) - priv, err := hd.DerivePrivateKeyForPath(master, ch, "44'/118'/0'/0/0") + priv, err := hd.DerivePrivateKeyForPath(master, ch, "m/44'/118'/0'/0/0") require.NoError(t, err) + privKey := &secp256k1.PrivKey{Key: priv} pub := privKey.PubKey() diff --git a/crypto/hd/hdpath.go b/crypto/hd/hdpath.go index 67a02f0290..04469d7305 100644 --- a/crypto/hd/hdpath.go +++ b/crypto/hd/hdpath.go @@ -36,52 +36,66 @@ func NewParams(purpose, coinType, account uint32, change bool, addressIdx uint32 } } -// Parse the BIP44 path and unmarshal into the struct. +// NewParamsFromPath parses the BIP44 path and unmarshals it into a Bip44Params. It supports both +// absolute and relative paths. func NewParamsFromPath(path string) (*BIP44Params, error) { spl := strings.Split(path, "/") + + // Handle absolute or relative paths + switch { + case spl[0] == path: + return nil, fmt.Errorf("path %s doesn't contain '/' separators", path) + + case strings.TrimSpace(spl[0]) == "": + return nil, fmt.Errorf("ambiguous path %s: use 'm/' prefix for absolute paths, or no leading '/' for relative ones", path) + + case strings.TrimSpace(spl[0]) == "m": + spl = spl[1:] + } + if len(spl) != 5 { - return nil, fmt.Errorf("path length is wrong. Expected 5, got %d", len(spl)) + return nil, fmt.Errorf("invalid path length %s", path) } // Check items can be parsed purpose, err := hardenedInt(spl[0]) if err != nil { - return nil, err + return nil, fmt.Errorf("invalid HD path purpose %s: %w", spl[0], err) } coinType, err := hardenedInt(spl[1]) if err != nil { - return nil, err + return nil, fmt.Errorf("invalid HD path coin type %s: %w", spl[1], err) } account, err := hardenedInt(spl[2]) if err != nil { - return nil, err + return nil, fmt.Errorf("invalid HD path account %s: %w", spl[2], err) } change, err := hardenedInt(spl[3]) if err != nil { - return nil, err + return nil, fmt.Errorf("invalid HD path change %s: %w", spl[3], err) } addressIdx, err := hardenedInt(spl[4]) if err != nil { - return nil, err + return nil, fmt.Errorf("invalid HD path address index %s: %w", spl[4], err) } // Confirm valid values if spl[0] != "44'" { - return nil, fmt.Errorf("first field in path must be 44', got %v", spl[0]) + return nil, fmt.Errorf("first field in path must be 44', got %s", spl[0]) } if !isHardened(spl[1]) || !isHardened(spl[2]) { return nil, - fmt.Errorf("second and third field in path must be hardened (ie. contain the suffix ', got %v and %v", spl[1], spl[2]) + fmt.Errorf("second and third field in path must be hardened (ie. contain the suffix ', got %s and %s", spl[1], spl[2]) } if isHardened(spl[3]) || isHardened(spl[4]) { return nil, - fmt.Errorf("fourth and fifth field in path must not be hardened (ie. not contain the suffix ', got %v and %v", spl[3], spl[4]) + fmt.Errorf("fourth and fifth field in path must not be hardened (ie. not contain the suffix ', got %s and %s", spl[3], spl[4]) } if !(change == 0 || change == 1) { @@ -135,6 +149,8 @@ func (p BIP44Params) DerivationPath() []uint32 { } } +// String returns the full absolute HD path of the BIP44 (https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) params: +// m / purpose' / coin_type' / account' / change / address_index func (p BIP44Params) String() string { var changeStr string if p.Change { @@ -142,8 +158,7 @@ func (p BIP44Params) String() string { } else { changeStr = "0" } - // m / Purpose' / coin_type' / Account' / Change / address_index - return fmt.Sprintf("%d'/%d'/%d'/%s/%d", + return fmt.Sprintf("m/%d'/%d'/%d'/%s/%d", p.Purpose, p.CoinType, p.Account, @@ -165,6 +180,13 @@ func DerivePrivateKeyForPath(privKeyBytes, chainCode [32]byte, path string) ([]b data := privKeyBytes parts := strings.Split(path, "/") + switch { + case parts[0] == path: + return nil, fmt.Errorf("path '%s' doesn't contain '/' separators", path) + case strings.TrimSpace(parts[0]) == "m": + parts = parts[1:] + } + for _, part := range parts { // do we have an apostrophe? harden := part[len(part)-1:] == "'" @@ -178,7 +200,7 @@ func DerivePrivateKeyForPath(privKeyBytes, chainCode [32]byte, path string) ([]b // index values are in the range [0, 1<<31-1] aka [0, max(int32)] idx, err := strconv.ParseUint(part, 10, 31) if err != nil { - return []byte{}, fmt.Errorf("invalid BIP 32 path: %s", err) + return []byte{}, fmt.Errorf("invalid BIP 32 path %s: %w", path, err) } data, chainCode = derivePrivateKey(data, chainCode, uint32(idx), harden) @@ -188,7 +210,7 @@ func DerivePrivateKeyForPath(privKeyBytes, chainCode [32]byte, path string) ([]b n := copy(derivedKey, data[:]) if n != 32 || len(data) != 32 { - return []byte{}, fmt.Errorf("expected a (secp256k1) key of length 32, got length: %v", len(data)) + return []byte{}, fmt.Errorf("expected a key of length 32, got length: %d", len(data)) } return derivedKey, nil diff --git a/crypto/hd/hdpath_test.go b/crypto/hd/hdpath_test.go index 42622b9a9c..2620e0605c 100644 --- a/crypto/hd/hdpath_test.go +++ b/crypto/hd/hdpath_test.go @@ -9,7 +9,6 @@ import ( "github.com/cosmos/cosmos-sdk/types" bip39 "github.com/cosmos/go-bip39" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -20,26 +19,22 @@ func mnemonicToSeed(mnemonic string) []byte { return bip39.NewSeed(mnemonic, defaultBIP39Passphrase) } -// nolint:govet -func ExampleStringifyPathParams() { +func TestPathParamsString(t *testing.T) { path := hd.NewParams(44, 0, 0, false, 0) - fmt.Println(path.String()) + require.Equal(t, "m/44'/0'/0'/0/0", path.String()) path = hd.NewParams(44, 33, 7, true, 9) - fmt.Println(path.String()) - // Output: - // 44'/0'/0'/0/0 - // 44'/33'/7'/1/9 + require.Equal(t, "m/44'/33'/7'/1/9", path.String()) } func TestStringifyFundraiserPathParams(t *testing.T) { path := hd.NewFundraiserParams(4, types.CoinType, 22) - require.Equal(t, "44'/118'/4'/0/22", path.String()) + require.Equal(t, "m/44'/118'/4'/0/22", path.String()) path = hd.NewFundraiserParams(4, types.CoinType, 57) - require.Equal(t, "44'/118'/4'/0/57", path.String()) + require.Equal(t, "m/44'/118'/4'/0/57", path.String()) path = hd.NewFundraiserParams(4, 12345, 57) - require.Equal(t, "44'/12345'/4'/0/57", path.String()) + require.Equal(t, "m/44'/12345'/4'/0/57", path.String()) } func TestPathToArray(t *testing.T) { @@ -55,95 +50,101 @@ func TestParamsFromPath(t *testing.T) { params *hd.BIP44Params path string }{ - {&hd.BIP44Params{44, 0, 0, false, 0}, "44'/0'/0'/0/0"}, - {&hd.BIP44Params{44, 1, 0, false, 0}, "44'/1'/0'/0/0"}, - {&hd.BIP44Params{44, 0, 1, false, 0}, "44'/0'/1'/0/0"}, - {&hd.BIP44Params{44, 0, 0, true, 0}, "44'/0'/0'/1/0"}, - {&hd.BIP44Params{44, 0, 0, false, 1}, "44'/0'/0'/0/1"}, - {&hd.BIP44Params{44, 1, 1, true, 1}, "44'/1'/1'/1/1"}, - {&hd.BIP44Params{44, 118, 52, true, 41}, "44'/118'/52'/1/41"}, + {&hd.BIP44Params{44, 0, 0, false, 0}, "m/44'/0'/0'/0/0"}, + {&hd.BIP44Params{44, 1, 0, false, 0}, "m/44'/1'/0'/0/0"}, + {&hd.BIP44Params{44, 0, 1, false, 0}, "m/44'/0'/1'/0/0"}, + {&hd.BIP44Params{44, 0, 0, true, 0}, "m/44'/0'/0'/1/0"}, + {&hd.BIP44Params{44, 0, 0, false, 1}, "m/44'/0'/0'/0/1"}, + {&hd.BIP44Params{44, 1, 1, true, 1}, "m/44'/1'/1'/1/1"}, + {&hd.BIP44Params{44, 118, 52, true, 41}, "m/44'/118'/52'/1/41"}, } for i, c := range goodCases { params, err := hd.NewParamsFromPath(c.path) errStr := fmt.Sprintf("%d %v", i, c) - assert.NoError(t, err, errStr) - assert.EqualValues(t, c.params, params, errStr) - assert.Equal(t, c.path, c.params.String()) + require.NoError(t, err, errStr) + require.EqualValues(t, c.params, params, errStr) + require.Equal(t, c.path, c.params.String()) } badCases := []struct { path string }{ - {"43'/0'/0'/0/0"}, // doesnt start with 44 - {"44'/1'/0'/0/0/5"}, // too many fields - {"44'/0'/1'/0"}, // too few fields - {"44'/0'/0'/2/0"}, // change field can only be 0/1 - {"44/0'/0'/0/0"}, // first field needs ' - {"44'/0/0'/0/0"}, // second field needs ' - {"44'/0'/0/0/0"}, // third field needs ' - {"44'/0'/0'/0'/0"}, // fourth field must not have ' - {"44'/0'/0'/0/0'"}, // fifth field must not have ' - {"44'/-1'/0'/0/0"}, // no negatives - {"44'/0'/0'/-1/0"}, // no negatives - {"a'/0'/0'/-1/0"}, // valid values - {"0/X/0'/-1/0"}, // valid values - {"44'/0'/X/-1/0"}, // valid values - {"44'/0'/0'/%/0"}, // valid values - {"44'/0'/0'/0/%"}, // valid values + {"m/43'/0'/0'/0/0"}, // doesn't start with 44 + {"m/44'/1'/0'/0/0/5"}, // too many fields + {"m/44'/0'/1'/0"}, // too few fields + {"m/44'/0'/0'/2/0"}, // change field can only be 0/1 + {"m/44/0'/0'/0/0"}, // first field needs ' + {"m/44'/0/0'/0/0"}, // second field needs ' + {"m/44'/0'/0/0/0"}, // third field needs ' + {"m/44'/0'/0'/0'/0"}, // fourth field must not have ' + {"m/44'/0'/0'/0/0'"}, // fifth field must not have ' + {"m/44'/-1'/0'/0/0"}, // no negatives + {"m/44'/0'/0'/-1/0"}, // no negatives + {"m/a'/0'/0'/-1/0"}, // invalid values + {"m/0/X/0'/-1/0"}, // invalid values + {"m/44'/0'/X/-1/0"}, // invalid values + {"m/44'/0'/0'/%/0"}, // invalid values + {"m/44'/0'/0'/0/%"}, // invalid values + {"m44'0'0'00"}, // no separators + {" /44'/0'/0'/0/0"}, // blank first component } for i, c := range badCases { params, err := hd.NewParamsFromPath(c.path) errStr := fmt.Sprintf("%d %v", i, c) - assert.Nil(t, params, errStr) - assert.Error(t, err, errStr) + require.Nil(t, params, errStr) + require.Error(t, err, errStr) } } -// nolint:govet -func ExampleSomeBIP32TestVecs() { +func TestBIP32Vecs(t *testing.T) { seed := mnemonicToSeed("barrel original fuel morning among eternal " + "filter ball stove pluck matrix mechanic") master, ch := hd.ComputeMastersFromSeed(seed) fmt.Println("keys from fundraiser test-vector (cosmos, bitcoin, ether)") fmt.Println() - // cosmos + + // cosmos, absolute path priv, err := hd.DerivePrivateKeyForPath(master, ch, types.FullFundraiserPath) - if err != nil { - fmt.Println("INVALID") - } else { - fmt.Println(hex.EncodeToString(priv[:])) - } + require.NoError(t, err) + require.NotEmpty(t, priv) + fmt.Println(hex.EncodeToString(priv[:])) + + absPrivKey := hex.EncodeToString(priv[:]) + + // cosmos, relative path + priv, err = hd.DerivePrivateKeyForPath(master, ch, "44'/118'/0'/0/0") + require.NoError(t, err) + require.NotEmpty(t, priv) + + relPrivKey := hex.EncodeToString(priv[:]) + + // check compatibility between relative and absolute HD paths + require.Equal(t, relPrivKey, absPrivKey) + // bitcoin - priv, err = hd.DerivePrivateKeyForPath(master, ch, "44'/0'/0'/0/0") - if err != nil { - fmt.Println("INVALID") - } else { - fmt.Println(hex.EncodeToString(priv[:])) - } + priv, err = hd.DerivePrivateKeyForPath(master, ch, "m/44'/0'/0'/0/0") + require.NoError(t, err) + require.NotEmpty(t, priv) + fmt.Println(hex.EncodeToString(priv[:])) + // ether - priv, err = hd.DerivePrivateKeyForPath(master, ch, "44'/60'/0'/0/0") - if err != nil { - fmt.Println("INVALID") - } else { - fmt.Println(hex.EncodeToString(priv[:])) - } + priv, err = hd.DerivePrivateKeyForPath(master, ch, "m/44'/60'/0'/0/0") + require.NoError(t, err) + require.NotEmpty(t, priv) + fmt.Println(hex.EncodeToString(priv[:])) + // INVALID - priv, err = hd.DerivePrivateKeyForPath(master, ch, "X/0'/0'/0/0") - if err != nil { - fmt.Println("INVALID") - } else { - fmt.Println(hex.EncodeToString(priv[:])) - } - priv, err = hd.DerivePrivateKeyForPath(master, ch, "-44/0'/0'/0/0") - if err != nil { - fmt.Println("INVALID") - } else { - fmt.Println(hex.EncodeToString(priv[:])) - } + priv, err = hd.DerivePrivateKeyForPath(master, ch, "m/X/0'/0'/0/0") + require.Error(t, err) + require.Empty(t, priv) + + priv, err = hd.DerivePrivateKeyForPath(master, ch, "m/-44/0'/0'/0/0") + require.Error(t, err) + require.Empty(t, priv) fmt.Println() fmt.Println("keys generated via https://coinomi.com/recovery-phrase-tool.html") @@ -153,13 +154,14 @@ func ExampleSomeBIP32TestVecs() { "advice process birth april short trust crater change bacon monkey medal garment " + "gorilla ranch hour rival razor call lunar mention taste vacant woman sister") master, ch = hd.ComputeMastersFromSeed(seed) - priv, _ = hd.DerivePrivateKeyForPath(master, ch, "44'/1'/1'/0/4") + priv, _ = hd.DerivePrivateKeyForPath(master, ch, "m/44'/1'/1'/0/4") fmt.Println(hex.EncodeToString(priv[:])) seed = mnemonicToSeed("idea naive region square margin day captain habit " + "gun second farm pact pulse someone armed") master, ch = hd.ComputeMastersFromSeed(seed) - priv, _ = hd.DerivePrivateKeyForPath(master, ch, "44'/0'/0'/0/420") + priv, err = hd.DerivePrivateKeyForPath(master, ch, "m/44'/0'/0'/0/420") + require.NoError(t, err) fmt.Println(hex.EncodeToString(priv[:])) fmt.Println() @@ -169,7 +171,8 @@ func ExampleSomeBIP32TestVecs() { // bip32 path: m/0/7 seed = mnemonicToSeed("monitor flock loyal sick object grunt duty ride develop assault harsh history") master, ch = hd.ComputeMastersFromSeed(seed) - priv, _ = hd.DerivePrivateKeyForPath(master, ch, "0/7") + priv, err = hd.DerivePrivateKeyForPath(master, ch, "m/0/7") + require.NoError(t, err) // TODO: shouldn't this error? fmt.Println(hex.EncodeToString(priv[:])) // Output: keys from fundraiser test-vector (cosmos, bitcoin, ether) @@ -177,8 +180,6 @@ func ExampleSomeBIP32TestVecs() { // bfcb217c058d8bbafd5e186eae936106ca3e943889b0b4a093ae13822fd3170c // e77c3de76965ad89997451de97b95bb65ede23a6bf185a55d80363d92ee37c3d // 7fc4d8a8146dea344ba04c593517d3f377fa6cded36cd55aee0a0bb968e651bc - // INVALID - // INVALID // // keys generated via https://coinomi.com/recovery-phrase-tool.html // @@ -201,9 +202,9 @@ func TestCreateHDPath(t *testing.T) { args args want hd.BIP44Params }{ - {"44'/0'/0'/0/0", args{0, 0, 0}, hd.BIP44Params{Purpose: 44}}, - {"44'/114'/0'/0/0", args{114, 0, 0}, hd.BIP44Params{Purpose: 44, CoinType: 114, Account: 0, AddressIndex: 0}}, - {"44'/114'/1'/1/0", args{114, 1, 1}, hd.BIP44Params{Purpose: 44, CoinType: 114, Account: 1, AddressIndex: 1}}, + {"m/44'/0'/0'/0/0", args{0, 0, 0}, hd.BIP44Params{Purpose: 44}}, + {"m/44'/114'/0'/0/0", args{114, 0, 0}, hd.BIP44Params{Purpose: 44, CoinType: 114, Account: 0, AddressIndex: 0}}, + {"m/44'/114'/1'/1/0", args{114, 1, 1}, hd.BIP44Params{Purpose: 44, CoinType: 114, Account: 1, AddressIndex: 1}}, } for _, tt := range tests { tt := tt @@ -227,36 +228,44 @@ func TestDeriveHDPathRange(t *testing.T) { wantErr string }{ { - path: "1'/2147483648/0'/0/0", + path: "m/1'/2147483648/0'/0/0", wantErr: "out of range", }, { - path: "2147483648'/1/0/0", + path: "m/2147483648'/1/0/0", wantErr: "out of range", }, { - path: "2147483648'/2147483648/0'/0/0", + path: "m/2147483648'/2147483648/0'/0/0", wantErr: "out of range", }, { - path: "1'/-5/0'/0/0", + path: "m/1'/-5/0'/0/0", wantErr: "invalid syntax", }, { - path: "-2147483646'/1/0/0", + path: "m/-2147483646'/1/0/0", wantErr: "invalid syntax", }, { - path: "-2147483648'/-2147483648/0'/0/0", + path: "m/-2147483648'/-2147483648/0'/0/0", wantErr: "invalid syntax", }, + { + path: "m44'118'0'00", + wantErr: "path 'm44'118'0'00' doesn't contain '/' separators", + }, + { + path: "", + wantErr: "path '' doesn't contain '/' separators", + }, { // Should pass. - path: "1'/2147483647/0'/0/0", + path: "m/1'/2147483647'/1/0'/0/0", }, { // Should pass. - path: "2147483647'/1/0'/0/0", + path: "1'/2147483647'/1/0'/0/0", }, } @@ -267,9 +276,9 @@ func TestDeriveHDPathRange(t *testing.T) { _, err := hd.DerivePrivateKeyForPath(master, ch, tt.path) if tt.wantErr == "" { - require.Nil(t, err, "unexpected error") + require.NoError(t, err, "unexpected error") } else { - require.NotNil(t, err, "expected a report of an int overflow") + require.Error(t, err, "expected a report of an int overflow") require.Contains(t, err.Error(), tt.wantErr) } }) diff --git a/crypto/keyring/keyring_ledger_test.go b/crypto/keyring/keyring_ledger_test.go index 275e3edd57..eb7e85f9e8 100644 --- a/crypto/keyring/keyring_ledger_test.go +++ b/crypto/keyring/keyring_ledger_test.go @@ -45,7 +45,7 @@ func TestInMemoryCreateLedger(t *testing.T) { path, err := restoredKey.GetPath() require.NoError(t, err) - require.Equal(t, "44'/118'/3'/0/1", path.String()) + require.Equal(t, "m/44'/118'/3'/0/1", path.String()) } // TestSignVerify does some detailed checks on how we sign and validate @@ -123,5 +123,5 @@ func TestAltKeyring_SaveLedgerKey(t *testing.T) { path, err := restoredKey.GetPath() require.NoError(t, err) - require.Equal(t, "44'/118'/3'/0/1", path.String()) + require.Equal(t, "m/44'/118'/3'/0/1", path.String()) } diff --git a/crypto/keyring/types_test.go b/crypto/keyring/types_test.go index ca99d9b7c5..8c68bce670 100644 --- a/crypto/keyring/types_test.go +++ b/crypto/keyring/types_test.go @@ -4,11 +4,10 @@ import ( "encoding/hex" "testing" - "github.com/stretchr/testify/assert" - "github.com/cosmos/cosmos-sdk/crypto/hd" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" ) func Test_writeReadLedgerInfo(t *testing.T) { @@ -17,28 +16,27 @@ func Test_writeReadLedgerInfo(t *testing.T) { copy(tmpKey[:], bz) lInfo := newLedgerInfo("some_name", &secp256k1.PubKey{Key: tmpKey}, *hd.NewFundraiserParams(5, sdk.CoinType, 1), hd.Secp256k1Type) - assert.Equal(t, TypeLedger, lInfo.GetType()) + require.Equal(t, TypeLedger, lInfo.GetType()) path, err := lInfo.GetPath() - assert.NoError(t, err) - assert.Equal(t, "44'/118'/5'/0/1", path.String()) - assert.Equal(t, + require.NoError(t, err) + require.Equal(t, "m/44'/118'/5'/0/1", path.String()) + require.Equal(t, "cosmospub1addwnpepqddddqg2glc8x4fl7vxjlnr7p5a3czm5kcdp4239sg6yqdc4rc2r5wmxv8p", sdk.MustBech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, lInfo.GetPubKey())) // Serialize and restore serialized := marshalInfo(lInfo) restoredInfo, err := unmarshalInfo(serialized) - assert.NoError(t, err) - assert.NotNil(t, restoredInfo) + require.NoError(t, err) + require.NotNil(t, restoredInfo) // Check both keys match - assert.Equal(t, lInfo.GetName(), restoredInfo.GetName()) - assert.Equal(t, lInfo.GetType(), restoredInfo.GetType()) - assert.Equal(t, lInfo.GetPubKey(), restoredInfo.GetPubKey()) + require.Equal(t, lInfo.GetName(), restoredInfo.GetName()) + require.Equal(t, lInfo.GetType(), restoredInfo.GetType()) + require.Equal(t, lInfo.GetPubKey(), restoredInfo.GetPubKey()) restoredPath, err := restoredInfo.GetPath() - assert.NoError(t, err) - - assert.Equal(t, path, restoredPath) + require.NoError(t, err) + require.Equal(t, path, restoredPath) } diff --git a/crypto/ledger/ledger_test.go b/crypto/ledger/ledger_test.go index bc85b2feba..5fe9da8f55 100644 --- a/crypto/ledger/ledger_test.go +++ b/crypto/ledger/ledger_test.go @@ -24,7 +24,7 @@ func TestErrorHandling(t *testing.T) { func TestPublicKeyUnsafe(t *testing.T) { path := *hd.NewFundraiserParams(0, sdk.CoinType, 0) priv, err := NewPrivKeySecp256k1Unsafe(path) - require.Nil(t, err, "%s", err) + require.NoError(t, err) require.NotNil(t, priv) require.Equal(t, "eb5ae98721034fef9cd7c4c63588d3b03feb5281b9d232cba34d6f3d71aee59211ffbfe1fe87", @@ -62,10 +62,10 @@ func TestPublicKeyUnsafeHDPath(t *testing.T) { // Check with device for i := uint32(0); i < 10; i++ { path := *hd.NewFundraiserParams(0, sdk.CoinType, i) - fmt.Printf("Checking keys at %v\n", path) + t.Logf("Checking keys at %v\n", path) priv, err := NewPrivKeySecp256k1Unsafe(path) - require.Nil(t, err, "%s", err) + require.NoError(t, err) require.NotNil(t, priv) // Check other methods @@ -100,7 +100,7 @@ func TestPublicKeySafe(t *testing.T) { path := *hd.NewFundraiserParams(0, sdk.CoinType, 0) priv, addr, err := NewPrivKeySecp256k1(path, "cosmos") - require.Nil(t, err, "%s", err) + require.NoError(t, err) require.NotNil(t, priv) require.Nil(t, ShowAddress(path, priv.PubKey(), sdk.GetConfig().GetBech32AccountAddrPrefix())) @@ -155,10 +155,10 @@ func TestPublicKeyHDPath(t *testing.T) { // Check with device for i := uint32(0); i < 10; i++ { path := *hd.NewFundraiserParams(0, sdk.CoinType, i) - fmt.Printf("Checking keys at %v\n", path) + t.Logf("Checking keys at %s\n", path) priv, addr, err := NewPrivKeySecp256k1(path, "cosmos") - require.Nil(t, err, "%s", err) + require.NoError(t, err) require.NotNil(t, addr) require.NotNil(t, priv) @@ -209,14 +209,14 @@ func TestSignaturesHD(t *testing.T) { msg := getFakeTx(account) path := *hd.NewFundraiserParams(account, sdk.CoinType, account/5) - fmt.Printf("Checking signature at %v --- PLEASE REVIEW AND ACCEPT IN THE DEVICE\n", path) + t.Logf("Checking signature at %v --- PLEASE REVIEW AND ACCEPT IN THE DEVICE\n", path) priv, err := NewPrivKeySecp256k1Unsafe(path) - require.Nil(t, err, "%s", err) + require.NoError(t, err) pub := priv.PubKey() sig, err := priv.Sign(msg) - require.Nil(t, err) + require.NoError(t, err) valid := pub.VerifySignature(msg, sig) require.True(t, valid, "Is your device using test mnemonic: %s ?", testutil.TestMnemonic) @@ -227,11 +227,11 @@ func TestRealDeviceSecp256k1(t *testing.T) { msg := getFakeTx(50) path := *hd.NewFundraiserParams(0, sdk.CoinType, 0) priv, err := NewPrivKeySecp256k1Unsafe(path) - require.Nil(t, err, "%s", err) + require.NoError(t, err) pub := priv.PubKey() sig, err := priv.Sign(msg) - require.Nil(t, err) + require.NoError(t, err) valid := pub.VerifySignature(msg, sig) require.True(t, valid) @@ -246,7 +246,7 @@ func TestRealDeviceSecp256k1(t *testing.T) { // signing with the loaded key should match the original pubkey sig, err = priv.Sign(msg) - require.Nil(t, err) + require.NoError(t, err) valid = pub.VerifySignature(msg, sig) require.True(t, valid) diff --git a/types/address.go b/types/address.go index a6d65e7a70..7e0408a849 100644 --- a/types/address.go +++ b/types/address.go @@ -31,15 +31,15 @@ const ( // AddrLen defines a valid address length AddrLen = 20 - // Bech32PrefixAccAddr defines the Bech32 prefix of an account's address + // Bech32MainPrefix defines the main SDK Bech32 prefix of an account's address Bech32MainPrefix = "cosmos" - // Atom in https://github.com/satoshilabs/slips/blob/master/slip-0044.md + // CoinType is the ATOM coin type as defined in SLIP44 (https://github.com/satoshilabs/slips/blob/master/slip-0044.md) CoinType = 118 - // BIP44Prefix is the parts of the BIP44 HD path that are fixed by - // what we used during the fundraiser. - FullFundraiserPath = "44'/118'/0'/0/0" + // FullFundraiserPath is the parts of the BIP44 HD path that are fixed by + // what we used during the ATOM fundraiser. + FullFundraiserPath = "m/44'/118'/0'/0/0" // PrefixAccount is the prefix for account keys PrefixAccount = "acc"