github.com/iotexproject/iotex-core@v1.14.1-rc1/ioctl/newcmd/hdwallet/hdwallet_test.go (about) 1 // Copyright (c) 2020 IoTeX Foundation 2 // This source code is provided 'as is' and no warranties are given as to title or non-infringement, merchantability 3 // or fitness for purpose and, to the extent permitted by law, all liability for your use of the code is disclaimed. 4 // This source code is governed by Apache License 2.0 that can be found in the LICENSE file. 5 6 package hdwallet 7 8 import ( 9 "encoding/hex" 10 "fmt" 11 "testing" 12 13 ecrypt "github.com/ethereum/go-ethereum/crypto" 14 "github.com/golang/mock/gomock" 15 "github.com/iotexproject/go-pkgs/crypto" 16 hdwallet "github.com/miguelmota/go-ethereum-hdwallet" 17 "github.com/stretchr/testify/require" 18 "github.com/tyler-smith/go-bip39" 19 20 "github.com/iotexproject/iotex-core/ioctl/config" 21 "github.com/iotexproject/iotex-core/ioctl/util" 22 "github.com/iotexproject/iotex-core/test/mock/mock_ioctlclient" 23 ) 24 25 func TestNewHdwalletCmd(t *testing.T) { 26 require := require.New(t) 27 ctrl := gomock.NewController(t) 28 defer ctrl.Finish() 29 client := mock_ioctlclient.NewMockClient(ctrl) 30 client.EXPECT().SelectTranslation(gomock.Any()).Return("hdwallet usage", config.English).Times(6) 31 cmd := NewHdwalletCmd(client) 32 result, err := util.ExecuteCmd(cmd) 33 require.NoError(err) 34 require.Contains(result, "Available Commands") 35 } 36 37 func Test_Hdwallet(t *testing.T) { 38 require := require.New(t) 39 40 // simulating 'hdwallet create' here 41 password := "123" 42 43 entropy, _ := bip39.NewEntropy(128) 44 mnemonic, _ := bip39.NewMnemonic(entropy) 45 46 enctxt := append([]byte(mnemonic), util.HashSHA256([]byte(mnemonic))...) 47 enckey := util.HashSHA256([]byte(password)) 48 49 out, err := util.Encrypt(enctxt, enckey) 50 require.NoError(err) 51 52 // simulating 'hdwallet use' here 53 enckey = util.HashSHA256([]byte(password)) 54 55 dectxt, err := util.Decrypt(out, enckey) 56 require.NoError(err) 57 58 dectxtLen := len(dectxt) 59 require.True(dectxtLen > 32) 60 61 mnemonic1, hash := dectxt[:dectxtLen-32], dectxt[dectxtLen-32:] 62 63 require.Equal(hash, util.HashSHA256(mnemonic1)) 64 65 wallet, err := hdwallet.NewFromMnemonic(string(mnemonic)) 66 require.NoError(err) 67 68 derivationPath := fmt.Sprintf("%s/0'/%d/%d", DefaultRootDerivationPath, 1, 2) 69 70 path := hdwallet.MustParseDerivationPath(derivationPath) 71 account, err := wallet.Derive(path, false) 72 require.NoError(err) 73 74 private1, err := wallet.PrivateKey(account) 75 require.NoError(err) 76 77 // simulating 'hdwallet import' here 78 enctxt = append([]byte(mnemonic), util.HashSHA256([]byte(mnemonic))...) 79 enckey = util.HashSHA256([]byte(password)) 80 81 _, err = util.Encrypt(enctxt, enckey) 82 require.NoError(err) 83 84 // compare import and create 85 wallet, err = hdwallet.NewFromMnemonic(string(mnemonic)) 86 require.NoError(err) 87 88 derivationPath = fmt.Sprintf("%s/0'/%d/%d", DefaultRootDerivationPath, 1, 2) 89 90 path = hdwallet.MustParseDerivationPath(derivationPath) 91 account, err = wallet.Derive(path, false) 92 require.NoError(err) 93 94 private2, err := wallet.PrivateKey(account) 95 require.NoError(err) 96 require.Equal(private1, private2) 97 98 //test DeriveKey 99 account1 := 0 100 change := 1 101 index := 2 102 103 derivationPath = fmt.Sprintf("%s/%d'/%d/%d", DefaultRootDerivationPath, account1, change, index) 104 path = hdwallet.MustParseDerivationPath(derivationPath) 105 account, err = wallet.Derive(path, false) 106 require.NoError(err) 107 108 private3, err := wallet.PrivateKey(account) 109 require.NoError(err) 110 111 require.Equal(private2, private3) 112 113 account1 = 123 114 derivationPath = fmt.Sprintf("%s/%d'/%d/%d", DefaultRootDerivationPath, account1, change, index) 115 path = hdwallet.MustParseDerivationPath(derivationPath) 116 account, err = wallet.Derive(path, false) 117 require.NoError(err) 118 119 private4, err := wallet.PrivateKey(account) 120 require.NoError(err) 121 require.NotEqual(private2, private4) 122 } 123 124 func TestEncryptDecryptWithMnemonic(t *testing.T) { 125 require := require.New(t) 126 127 mnemonic := "lake stove quarter shove dry matrix hire split wide attract argue core" 128 password := "123" 129 130 enckey := util.HashSHA256([]byte(password)) 131 132 storedTxt, err := hex.DecodeString("4da6571c2897e88568cbcce59dcf9574355d718da25f2ea6f2e6847b9254fc18eacd852d282f1be7b51024fb05e70ee41bc08c0a8a07c549b0c29f185de0fb35462f98b429ebc4b79bfbcab41b795fe1e59262ae0695a4107dcc57a8bad24eb2323b2c976a9fb3dafc8788a9fccbf5b8c36e3388e458") 133 require.NoError(err) 134 135 dectxt, err := util.Decrypt(storedTxt, enckey) 136 require.NoError(err) 137 138 dectxtLen := len(dectxt) 139 140 mnemonic1, hash := dectxt[:dectxtLen-32], dectxt[dectxtLen-32:] 141 142 require.Equal(mnemonic, string(mnemonic1)) 143 require.Equal(util.HashSHA256(mnemonic1), hash) 144 } 145 146 func TestFixedMnemonicAndDerivationPath(t *testing.T) { 147 require := require.New(t) 148 149 mnemonic := "lake stove quarter shove dry matrix hire split wide attract argue core" 150 wallet, err := hdwallet.NewFromMnemonic(mnemonic) 151 require.NoError(err) 152 153 derivationPath := "m/44'/304'/0'/1/3" 154 155 path := hdwallet.MustParseDerivationPath(derivationPath) 156 account, err := wallet.Derive(path, false) 157 require.NoError(err) 158 159 private, err := wallet.PrivateKey(account) 160 require.NoError(err) 161 prvKey, err := crypto.BytesToPrivateKey(ecrypt.FromECDSA(private)) 162 require.NoError(err) 163 addr := prvKey.PublicKey().Address() 164 require.NotNil(addr) 165 166 require.Equal(addr.String(), "io13hwqt04le40puf73aa9w9zm9fq04qqn7qcjc6z") 167 168 }