extkeys/mnemonic_test.go

128 lines
3.3 KiB
Go

package extkeys
import (
"encoding/json"
"fmt"
"os"
"testing"
)
type VectorsFile struct {
Data map[string][][6]string
vectors []*Vector
}
type Vector struct {
language, password, input, mnemonic, seed, xprv string
}
func TestNewMnemonic(t *testing.T) {
m1 := NewMnemonic()
if m1.salt != defaultSalt {
t.Errorf("expected default salt, got: %q", m1.salt)
}
}
func TestMnemonic_WordList(t *testing.T) {
m := NewMnemonic()
_, err := m.WordList(EnglishLanguage)
if err != nil {
t.Errorf("expected WordList to return WordList without errors, got: %s", err)
}
indexes := []Language{-1, Language(len(m.wordLists))}
for _, index := range indexes {
_, err := m.WordList(index)
if err == nil {
t.Errorf("expected WordList to return an error with index %d", index)
}
}
}
// TestMnemonicPhrase
func TestMnemonicPhrase(t *testing.T) {
mnemonic := NewMnemonic()
// test strength validation
strengths := []EntropyStrength{127, 129, 257}
for _, s := range strengths {
_, err := mnemonic.MnemonicPhrase(s, EnglishLanguage)
if err != ErrInvalidEntropyStrength {
t.Errorf("Entropy strength '%d' should be invalid", s)
}
}
// test mnemonic generation
t.Log("Test mnemonic generation:")
for _, language := range mnemonic.AvailableLanguages() {
phrase, err := mnemonic.MnemonicPhrase(EntropyStrength128, language)
t.Logf("Mnemonic (%s): %s", Languages[language], phrase)
if err != nil {
t.Errorf("Test failed: could not create seed: %s", err)
}
if !mnemonic.ValidMnemonic(phrase, language) {
t.Error("Seed is not valid Mnenomic")
}
}
// run against test vectors
vectorsFile, err := LoadVectorsFile("mnemonic_vectors.json")
if err != nil {
t.Error(err)
}
t.Log("Test against pre-computed seed vectors:")
stats := map[string]int{}
for _, vector := range vectorsFile.vectors {
stats[vector.language]++
mnemonic := NewMnemonic()
seed := mnemonic.MnemonicSeed(vector.mnemonic, vector.password)
if fmt.Sprintf("%x", seed) != vector.seed {
t.Errorf("Test failed (%s): incorrect seed (%x) generated (expected: %s)", vector.language, seed, vector.seed)
return
}
//t.Logf("Test passed: correct seed (%x) generated (expected: %s)", seed, vector.seed)
rootKey, err := NewMaster(seed)
if err != nil {
t.Error(err)
}
if rootKey.String() != vector.xprv {
t.Errorf("Test failed (%s): incorrect xprv (%s) generated (expected: %s)", vector.language, rootKey, vector.xprv)
}
}
for language, count := range stats {
t.Logf("[%s]: %d tests completed", language, count)
}
}
func LoadVectorsFile(path string) (*VectorsFile, error) {
fp, err := os.Open(path)
if err != nil {
return nil, fmt.Errorf("Test failed: cannot open vectors file: %s", err)
}
var vectorsFile VectorsFile
if err := json.NewDecoder(fp).Decode(&vectorsFile); err != nil {
return nil, fmt.Errorf("Test failed: cannot parse vectors file: %s", err)
}
// load data into Vector structs
for language, data := range vectorsFile.Data {
for _, item := range data {
vectorsFile.vectors = append(vectorsFile.vectors, &Vector{language, item[0], item[1], item[2], item[3], item[4]})
}
}
return &vectorsFile, nil
}
func (v *Vector) String() string {
return fmt.Sprintf("{password: %s, input: %s, mnemonic: %s, seed: %s, xprv: %s}",
v.password, v.input, v.mnemonic, v.seed, v.xprv)
}