mnemonic: optimize fromPhrase.

This commit is contained in:
Christopher Jeffrey 2017-08-09 18:17:25 -07:00
parent fbd99ea1b9
commit bff9e25796
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD

View File

@ -19,6 +19,12 @@ const wordlist = require('./wordlist');
const common = require('./common');
const nfkd = require('../utils/nfkd');
/*
* Constants
*/
const wordlistCache = new Map();
/**
* HD Mnemonic
* @alias module:hd.Mnemonic
@ -191,7 +197,7 @@ Mnemonic.prototype.getPhrase = function getPhrase() {
// Build the mnemonic by reading
// 11 bit indexes from the entropy.
const wordlist = Mnemonic.getWordlist(this.language);
const list = Mnemonic.getWordlist(this.language);
let phrase = [];
for (let i = 0; i < bits / 11; i++) {
@ -203,7 +209,7 @@ Mnemonic.prototype.getPhrase = function getPhrase() {
index <<= 1;
index |= (entropy[oct] >>> (7 - bit)) & 1;
}
phrase.push(wordlist[index]);
phrase.push(list.words[index]);
}
// Japanese likes double-width spaces.
@ -224,6 +230,9 @@ Mnemonic.prototype.getPhrase = function getPhrase() {
*/
Mnemonic.prototype.fromPhrase = function fromPhrase(phrase) {
assert(typeof phrase === 'string');
assert(phrase.length <= 1000);
const words = phrase.split(/[ \u3000]+/);
let bits = words.length * 11;
const cbits = bits % 32;
@ -240,14 +249,14 @@ Mnemonic.prototype.fromPhrase = function fromPhrase(phrase) {
ent.fill(0);
const lang = Mnemonic.getLanguage(words[0]);
const wordlist = Mnemonic.getWordlist(lang);
const list = Mnemonic.getWordlist(lang);
// Rebuild entropy bytes.
for (let i = 0; i < words.length; i++) {
const word = words[i];
const index = wordlist.indexOf(word);
const index = list.map.get(word);
if (index === -1)
if (index == null)
throw new Error('Could not find word.');
for (let j = 0; j < 11; j++) {
@ -267,9 +276,9 @@ Mnemonic.prototype.fromPhrase = function fromPhrase(phrase) {
for (let i = 0; i < cbits; i++) {
const bit = i % 8;
const oct = (i - bit) / 8;
const a = (chk1[oct] >>> (7 - bit)) & 1;
const b = (chk2[oct] >>> (7 - bit)) & 1;
if (a !== b)
const b1 = (chk1[oct] >>> (7 - bit)) & 1;
const b2 = (chk2[oct] >>> (7 - bit)) & 1;
if (b1 !== b2)
throw new Error('Invalid checksum.');
}
@ -337,8 +346,8 @@ Mnemonic.fromEntropy = function fromEntropy(entropy, lang) {
Mnemonic.getLanguage = function getLanguage(word) {
for (const lang of Mnemonic.languages) {
const wordlist = Mnemonic.getWordlist(lang);
if (wordlist.indexOf(word) !== -1)
const list = Mnemonic.getWordlist(lang);
if (list.map.has(word))
return lang;
}
@ -347,12 +356,22 @@ Mnemonic.getLanguage = function getLanguage(word) {
/**
* Retrieve the wordlist for a language.
* @param {String} language
* @returns {String[]}
* @param {String} lang
* @returns {Object}
*/
Mnemonic.getWordlist = function getWordlist(language) {
return wordlist.get(language);
Mnemonic.getWordlist = function getWordlist(lang) {
const cache = wordlistCache.get(lang);
if (cache)
return cache;
const words = wordlist.get(lang);
const list = new WordList(words);
wordlistCache.set(lang, list);
return list;
};
/**
@ -530,6 +549,23 @@ Mnemonic.isMnemonic = function isMnemonic(obj) {
&& typeof obj.toSeed === 'function';
};
/**
* Word List
* @constructor
* @ignore
* @param {Array} words
*/
function WordList(words) {
this.words = words;
this.map = new Map();
for (let i = 0; i < words.length; i++) {
const word = words[i];
this.map.set(word, i);
}
}
/*
* Expose
*/