github.com/status-im/status-go@v1.1.0/account/generator/generator_test.go (about)

     1  package generator
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  	"testing"
     7  
     8  	"github.com/stretchr/testify/assert"
     9  
    10  	"github.com/ethereum/go-ethereum/crypto"
    11  )
    12  
    13  var testAccount = struct {
    14  	mnemonic           string
    15  	bip39Passphrase    string
    16  	encriptionPassword string
    17  	extendedMasterKey  string
    18  	bip44Key0          string
    19  	bip44PubKey0       string
    20  	bip44Address0      string
    21  	bip44Address1      string
    22  }{
    23  	mnemonic:           "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about",
    24  	bip39Passphrase:    "TREZOR",
    25  	encriptionPassword: "TEST_PASSWORD",
    26  	extendedMasterKey:  "xprv9s21ZrQH143K3h3fDYiay8mocZ3afhfULfb5GX8kCBdno77K4HiA15Tg23wpbeF1pLfs1c5SPmYHrEpTuuRhxMwvKDwqdKiGJS9XFKzUsAF",
    27  	bip44Key0:          "0x62f1d86b246c81bdd8f6c166d56896a4a5e1eddbcaebe06480e5c0bc74c28224",
    28  	bip44PubKey0:       "0x04986dee3b8afe24cb8ccb2ac23dac3f8c43d22850d14b809b26d6b8aa5a1f47784152cd2c7d9edd0ab20392a837464b5a750b2a7f3f06e6a5756b5211b6a6ed05",
    29  	bip44Address0:      "0x9c32F71D4DB8Fb9e1A58B0a80dF79935e7256FA6",
    30  	bip44Address1:      "0x7AF7283bd1462C3b957e8FAc28Dc19cBbF2FAdfe",
    31  }
    32  
    33  const testAccountJSONFile = `{
    34  	"address":"9c32f71d4db8fb9e1a58b0a80df79935e7256fa6",
    35  	"crypto":
    36  		{
    37  			"cipher":"aes-128-ctr","ciphertext":"8055b65d5e41ef467c0cfe52ce6beda7f8dbe689221c6c43be9e9401bf173004",
    38  			"cipherparams":{"iv":"738f002e5e5343e0bb0e1050e098f721"},
    39  			"kdf":"scrypt",
    40  			"kdfparams":{"dklen":32,"n":4096,"p":6,"r":8,"salt":"9a54fbe1439ac567bd05039f76907b2c2846364a38b2f6813bcdac5ab0ec9d18"},
    41  			"mac":"79d817cd21afd4944e70d804d7871d10cbd15f25c6755416f780f81c1588677e"
    42  		},
    43  	"id":"6202ced9-f0cd-42e4-bf21-6029cca0ea91",
    44  	"version":3
    45  }`
    46  
    47  const (
    48  	path0 = "m/44'/60'/0'/0/0"
    49  	path1 = "m/44'/60'/0'/0/1"
    50  )
    51  
    52  func TestGenerator_Generate(t *testing.T) {
    53  	g := New(nil)
    54  	assert.Equal(t, 0, len(g.accounts))
    55  
    56  	accountsInfo, err := g.Generate(12, 5, "")
    57  	assert.NoError(t, err)
    58  	assert.Equal(t, 5, len(g.accounts))
    59  
    60  	for _, info := range accountsInfo {
    61  		words := strings.Split(info.Mnemonic, " ")
    62  		assert.Equal(t, 12, len(words))
    63  	}
    64  }
    65  
    66  func TestGenerator_CreateAccountFromPrivateKey(t *testing.T) {
    67  	g := New(nil)
    68  	assert.Equal(t, 0, len(g.accounts))
    69  
    70  	info, err := g.CreateAccountFromPrivateKey(testAccount.bip44Key0)
    71  
    72  	assert.NoError(t, err)
    73  	assert.Equal(t, 0, len(g.accounts))
    74  	assert.Equal(t, 66, len(info.KeyUID))
    75  }
    76  
    77  func TestGenerator_ImportPrivateKey(t *testing.T) {
    78  	g := New(nil)
    79  	assert.Equal(t, 0, len(g.accounts))
    80  
    81  	info, err := g.ImportPrivateKey(testAccount.bip44Key0)
    82  	assert.NoError(t, err)
    83  	assert.Equal(t, 1, len(g.accounts))
    84  
    85  	assert.Equal(t, testAccount.bip44PubKey0, info.PublicKey)
    86  	assert.Equal(t, testAccount.bip44Address0, info.Address)
    87  }
    88  
    89  func TestGenerator_CreateAccountFromMnemonicAndDeriveAccountsForPaths(t *testing.T) {
    90  	g := New(nil)
    91  	assert.Equal(t, 0, len(g.accounts))
    92  
    93  	info, err := g.CreateAccountFromMnemonicAndDeriveAccountsForPaths(testAccount.mnemonic, testAccount.bip39Passphrase, []string{path0, path1})
    94  
    95  	assert.NoError(t, err)
    96  	assert.Equal(t, 0, len(g.accounts))
    97  	assert.Equal(t, 66, len(info.KeyUID))
    98  
    99  	assert.Equal(t, testAccount.bip44Address0, info.Derived[path0].Address)
   100  	assert.Equal(t, testAccount.bip44Address1, info.Derived[path1].Address)
   101  }
   102  
   103  func TestGenerator_ImportMnemonic(t *testing.T) {
   104  	g := New(nil)
   105  	assert.Equal(t, 0, len(g.accounts))
   106  
   107  	info, err := g.ImportMnemonic(testAccount.mnemonic, testAccount.bip39Passphrase)
   108  	assert.NoError(t, err)
   109  	assert.Equal(t, 1, len(g.accounts))
   110  
   111  	key := g.accounts[info.ID]
   112  	assert.Equal(t, testAccount.extendedMasterKey, key.extendedKey.String())
   113  }
   114  
   115  func TestGenerator_ImportJSONKey(t *testing.T) {
   116  	g := New(nil)
   117  	assert.Equal(t, 0, len(g.accounts))
   118  
   119  	// wrong password
   120  	_, err := g.ImportJSONKey(testAccountJSONFile, "wrong-password")
   121  	assert.Error(t, err)
   122  
   123  	// right password
   124  	info, err := g.ImportJSONKey(testAccountJSONFile, testAccount.encriptionPassword)
   125  	assert.NoError(t, err)
   126  	assert.Equal(t, 1, len(g.accounts))
   127  	assert.Equal(t, testAccount.bip44Address0, info.Address)
   128  
   129  	key := g.accounts[info.ID]
   130  	keyHex := fmt.Sprintf("0x%x", crypto.FromECDSA(key.privateKey))
   131  	assert.Equal(t, testAccount.bip44Key0, keyHex)
   132  }
   133  
   134  func TestGenerator_DeriveAddresses(t *testing.T) {
   135  	g := New(nil)
   136  	assert.Equal(t, 0, len(g.accounts))
   137  
   138  	info, err := g.ImportMnemonic(testAccount.mnemonic, testAccount.bip39Passphrase)
   139  	assert.NoError(t, err)
   140  	assert.Equal(t, 1, len(g.accounts))
   141  
   142  	addresses, err := g.DeriveAddresses(info.ID, []string{path0, path1})
   143  	assert.NoError(t, err)
   144  
   145  	assert.Equal(t, testAccount.bip44Address0, addresses[path0].Address)
   146  	assert.Equal(t, testAccount.bip44Address1, addresses[path1].Address)
   147  }
   148  
   149  func TestGenerator_DeriveAddresses_FromImportedPrivateKey(t *testing.T) {
   150  	g := New(nil)
   151  	assert.Equal(t, 0, len(g.accounts))
   152  
   153  	key, err := crypto.GenerateKey()
   154  	assert.NoError(t, err)
   155  	hex := fmt.Sprintf("%#x", crypto.FromECDSA(key))
   156  	info, err := g.ImportPrivateKey(hex)
   157  	assert.NoError(t, err)
   158  	assert.Equal(t, 1, len(g.accounts))
   159  
   160  	// normal imported accounts cannot derive child accounts,
   161  	// but only the address/pubblic key of the current key.
   162  	paths := []string{"", "m"}
   163  	for _, path := range paths {
   164  		addresses, err := g.DeriveAddresses(info.ID, []string{path})
   165  		assert.NoError(t, err)
   166  
   167  		expectedAddress := crypto.PubkeyToAddress(key.PublicKey).Hex()
   168  		assert.Equal(t, expectedAddress, addresses[path].Address)
   169  	}
   170  
   171  	// cannot derive other child keys from a normal key
   172  	_, err = g.DeriveAddresses(info.ID, []string{"m/0/1/2"})
   173  	assert.Equal(t, ErrAccountCannotDeriveChildKeys, err)
   174  }