mirror of
https://github.com/status-im/status-go.git
synced 2025-01-09 06:12:55 +00:00
c1c7d2dbf6
`CreateAccountFromMnemonic` function renamed to `createAccountFromMnemonicAndDeriveAccountsForPaths` and extended in a way that it is able to derive accounts from passed mnemonic for the given paths, if paths is empty only an account from the given mnemonic will be generated. This endpoint doesn't store anything anywhere.
160 lines
5.0 KiB
Go
160 lines
5.0 KiB
Go
package generator
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/ethereum/go-ethereum/crypto"
|
|
)
|
|
|
|
var testAccount = struct {
|
|
mnemonic string
|
|
bip39Passphrase string
|
|
encriptionPassword string
|
|
extendedMasterKey string
|
|
bip44Key0 string
|
|
bip44PubKey0 string
|
|
bip44Address0 string
|
|
bip44Address1 string
|
|
}{
|
|
mnemonic: "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about",
|
|
bip39Passphrase: "TREZOR",
|
|
encriptionPassword: "TEST_PASSWORD",
|
|
extendedMasterKey: "xprv9s21ZrQH143K3h3fDYiay8mocZ3afhfULfb5GX8kCBdno77K4HiA15Tg23wpbeF1pLfs1c5SPmYHrEpTuuRhxMwvKDwqdKiGJS9XFKzUsAF",
|
|
bip44Key0: "0x62f1d86b246c81bdd8f6c166d56896a4a5e1eddbcaebe06480e5c0bc74c28224",
|
|
bip44PubKey0: "0x04986dee3b8afe24cb8ccb2ac23dac3f8c43d22850d14b809b26d6b8aa5a1f47784152cd2c7d9edd0ab20392a837464b5a750b2a7f3f06e6a5756b5211b6a6ed05",
|
|
bip44Address0: "0x9c32F71D4DB8Fb9e1A58B0a80dF79935e7256FA6",
|
|
bip44Address1: "0x7AF7283bd1462C3b957e8FAc28Dc19cBbF2FAdfe",
|
|
}
|
|
|
|
const testAccountJSONFile = `{
|
|
"address":"9c32f71d4db8fb9e1a58b0a80df79935e7256fa6",
|
|
"crypto":
|
|
{
|
|
"cipher":"aes-128-ctr","ciphertext":"8055b65d5e41ef467c0cfe52ce6beda7f8dbe689221c6c43be9e9401bf173004",
|
|
"cipherparams":{"iv":"738f002e5e5343e0bb0e1050e098f721"},
|
|
"kdf":"scrypt",
|
|
"kdfparams":{"dklen":32,"n":4096,"p":6,"r":8,"salt":"9a54fbe1439ac567bd05039f76907b2c2846364a38b2f6813bcdac5ab0ec9d18"},
|
|
"mac":"79d817cd21afd4944e70d804d7871d10cbd15f25c6755416f780f81c1588677e"
|
|
},
|
|
"id":"6202ced9-f0cd-42e4-bf21-6029cca0ea91",
|
|
"version":3
|
|
}`
|
|
|
|
func TestGenerator_Generate(t *testing.T) {
|
|
g := New(nil)
|
|
assert.Equal(t, 0, len(g.accounts))
|
|
|
|
accountsInfo, err := g.Generate(12, 5, "")
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 5, len(g.accounts))
|
|
|
|
for _, info := range accountsInfo {
|
|
words := strings.Split(info.Mnemonic, " ")
|
|
assert.Equal(t, 12, len(words))
|
|
}
|
|
}
|
|
|
|
func TestGenerator_ImportPrivateKey(t *testing.T) {
|
|
g := New(nil)
|
|
assert.Equal(t, 0, len(g.accounts))
|
|
|
|
info, err := g.ImportPrivateKey(testAccount.bip44Key0)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 1, len(g.accounts))
|
|
|
|
assert.Equal(t, testAccount.bip44PubKey0, info.PublicKey)
|
|
assert.Equal(t, testAccount.bip44Address0, info.Address)
|
|
}
|
|
|
|
func TestGenerator_CreateAccountFromMnemonicAndDeriveAccountsForPaths(t *testing.T) {
|
|
g := New(nil)
|
|
assert.Equal(t, 0, len(g.accounts))
|
|
|
|
info, err := g.CreateAccountFromMnemonicAndDeriveAccountsForPaths(testAccount.mnemonic, testAccount.bip39Passphrase, []string{})
|
|
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 0, len(g.accounts))
|
|
assert.Equal(t, 36, len(info.ID))
|
|
assert.Equal(t, 66, len(info.KeyUID))
|
|
}
|
|
|
|
func TestGenerator_ImportMnemonic(t *testing.T) {
|
|
g := New(nil)
|
|
assert.Equal(t, 0, len(g.accounts))
|
|
|
|
info, err := g.ImportMnemonic(testAccount.mnemonic, testAccount.bip39Passphrase)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 1, len(g.accounts))
|
|
|
|
key := g.accounts[info.ID]
|
|
assert.Equal(t, testAccount.extendedMasterKey, key.extendedKey.String())
|
|
}
|
|
|
|
func TestGenerator_ImportJSONKey(t *testing.T) {
|
|
g := New(nil)
|
|
assert.Equal(t, 0, len(g.accounts))
|
|
|
|
// wrong password
|
|
_, err := g.ImportJSONKey(testAccountJSONFile, "wrong-password")
|
|
assert.Error(t, err)
|
|
|
|
// right password
|
|
info, err := g.ImportJSONKey(testAccountJSONFile, testAccount.encriptionPassword)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 1, len(g.accounts))
|
|
assert.Equal(t, testAccount.bip44Address0, info.Address)
|
|
|
|
key := g.accounts[info.ID]
|
|
keyHex := fmt.Sprintf("0x%x", crypto.FromECDSA(key.privateKey))
|
|
assert.Equal(t, testAccount.bip44Key0, keyHex)
|
|
}
|
|
|
|
func TestGenerator_DeriveAddresses(t *testing.T) {
|
|
g := New(nil)
|
|
assert.Equal(t, 0, len(g.accounts))
|
|
|
|
info, err := g.ImportMnemonic(testAccount.mnemonic, testAccount.bip39Passphrase)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 1, len(g.accounts))
|
|
|
|
path0 := "m/44'/60'/0'/0/0"
|
|
path1 := "m/44'/60'/0'/0/1"
|
|
|
|
addresses, err := g.DeriveAddresses(info.ID, []string{path0, path1})
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, testAccount.bip44Address0, addresses[path0].Address)
|
|
assert.Equal(t, testAccount.bip44Address1, addresses[path1].Address)
|
|
}
|
|
|
|
func TestGenerator_DeriveAddresses_FromImportedPrivateKey(t *testing.T) {
|
|
g := New(nil)
|
|
assert.Equal(t, 0, len(g.accounts))
|
|
|
|
key, err := crypto.GenerateKey()
|
|
assert.NoError(t, err)
|
|
hex := fmt.Sprintf("%#x", crypto.FromECDSA(key))
|
|
info, err := g.ImportPrivateKey(hex)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 1, len(g.accounts))
|
|
|
|
// normal imported accounts cannot derive child accounts,
|
|
// but only the address/pubblic key of the current key.
|
|
paths := []string{"", "m"}
|
|
for _, path := range paths {
|
|
addresses, err := g.DeriveAddresses(info.ID, []string{path})
|
|
assert.NoError(t, err)
|
|
|
|
expectedAddress := crypto.PubkeyToAddress(key.PublicKey).Hex()
|
|
assert.Equal(t, expectedAddress, addresses[path].Address)
|
|
}
|
|
|
|
// cannot derive other child keys from a normal key
|
|
_, err = g.DeriveAddresses(info.ID, []string{"m/0/1/2"})
|
|
assert.Equal(t, ErrAccountCannotDeriveChildKeys, err)
|
|
}
|