status-go/account/generator/generator_test.go

175 lines
5.4 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
}`
const (
path0 = "m/44'/60'/0'/0/0"
path1 = "m/44'/60'/0'/0/1"
)
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_CreateAccountFromPrivateKey(t *testing.T) {
g := New(nil)
assert.Equal(t, 0, len(g.accounts))
info, err := g.CreateAccountFromPrivateKey(testAccount.bip44Key0)
assert.NoError(t, err)
assert.Equal(t, 0, len(g.accounts))
assert.Equal(t, 66, len(info.KeyUID))
}
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{path0, path1})
assert.NoError(t, err)
assert.Equal(t, 0, len(g.accounts))
assert.Equal(t, 66, len(info.KeyUID))
assert.Equal(t, testAccount.bip44Address0, info.Derived[path0].Address)
assert.Equal(t, testAccount.bip44Address1, info.Derived[path1].Address)
}
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))
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)
}