Blank entropy does not generate addresses

This commit is contained in:
Ian Coleman
2016-11-07 11:51:12 +11:00
parent 52e6eb81c8
commit 057722b034
2 changed files with 176 additions and 70 deletions

View File

@@ -109,6 +109,7 @@
DOM.entropyContainer.addClass("hidden"); DOM.entropyContainer.addClass("hidden");
DOM.generateContainer.removeClass("hidden"); DOM.generateContainer.removeClass("hidden");
DOM.phrase.prop("readonly", false); DOM.phrase.prop("readonly", false);
hidePending();
} }
} }
@@ -149,8 +150,31 @@
} }
function entropyChanged() { function entropyChanged() {
// If blank entropy, clear mnemonic, addresses, errors
if (DOM.entropy.val().trim().length == 0) {
clearDisplay();
hideEntropyError();
DOM.phrase.val("");
showValidationError("Blank entropy");
return;
}
// Get the current phrase to detect changes
var phrase = DOM.phrase.val();
// Set the phrase from the entropy
setMnemonicFromEntropy(); setMnemonicFromEntropy();
phraseChanged(); // Recalc addresses if the phrase has changed
var newPhrase = DOM.phrase.val();
if (newPhrase != phrase) {
if (newPhrase.length == 0) {
clearDisplay();
}
else {
phraseChanged();
}
}
else {
hidePending();
}
} }
function delayedRootKeyChanged() { function delayedRootKeyChanged() {
@@ -311,10 +335,13 @@
} }
function findPhraseErrors(phrase) { function findPhraseErrors(phrase) {
// TODO make this right
// Preprocess the words // Preprocess the words
phrase = mnemonic.normalizeString(phrase); phrase = mnemonic.normalizeString(phrase);
var words = phraseToWordArray(phrase); var words = phraseToWordArray(phrase);
// Detect blank phrase
if (words.length == 0) {
return "Blank mnemonic";
}
// Check each word // Check each word
for (var i=0; i<words.length; i++) { for (var i=0; i<words.length; i++) {
var word = words[i]; var word = words[i];
@@ -701,10 +728,11 @@
function setMnemonicFromEntropy() { function setMnemonicFromEntropy() {
hideEntropyError(); hideEntropyError();
// Work out minimum base for entropy // Get entropy value
var entropyStr = DOM.entropy.val(); var entropyStr = DOM.entropy.val();
// Work out minimum base for entropy
var entropy = Entropy.fromString(entropyStr); var entropy = Entropy.fromString(entropyStr);
if (entropy.hexStr.length == 0) { if (entropy.binaryStr.length == 0) {
return; return;
} }
// Show entropy details // Show entropy details

210
tests.js
View File

@@ -75,6 +75,40 @@ function waitForFeedback(fn, maxTime) {
wait(); wait();
} }
function waitForEntropyFeedback(fn, maxTime) {
if (!maxTime) {
maxTime = testMaxTime;
}
var origFeedback = page.evaluate(function() {
return $(".entropy-error").text();
});
var start = new Date().getTime();
var wait = function keepWaiting() {
var now = new Date().getTime();
var hasTimedOut = now - start > maxTime;
if (hasTimedOut) {
console.log("Test timed out");
fn();
return;
}
var feedback = page.evaluate(function() {
var feedback = $(".entropy-error");
if (feedback.css("display") == "none") {
return "";
}
return feedback.text();
});
var hasFinished = feedback != origFeedback;
if (hasFinished) {
fn();
}
else {
setTimeout(keepWaiting, 100);
}
}
wait();
}
function next() { function next() {
if (tests.length > 0) { if (tests.length > 0) {
var testsStr = tests.length == 1 ? "test" : "tests"; var testsStr = tests.length == 1 ? "test" : "tests";
@@ -2146,7 +2180,7 @@ page.open(url, function(status) {
$(".entropy").val(entropy).trigger("input"); $(".entropy").val(entropy).trigger("input");
}); });
// check the actual entropy being used is shown // check the actual entropy being used is shown
waitForGenerate(function() { waitForEntropyFeedback(function() {
var expectedText = "AedEceAA"; var expectedText = "AedEceAA";
var entropyText = page.evaluate(function() { var entropyText = page.evaluate(function() {
return $(".entropy-container").text(); return $(".entropy-container").text();
@@ -2169,7 +2203,7 @@ page.open(url, function(status) {
$(".entropy").val("01").trigger("input"); $(".entropy").val("01").trigger("input");
}); });
// check the entropy is shown to be the correct type // check the entropy is shown to be the correct type
waitForGenerate(function() { waitForEntropyFeedback(function() {
var entropyText = page.evaluate(function() { var entropyText = page.evaluate(function() {
return $(".entropy-container").text(); return $(".entropy-container").text();
}); });
@@ -2191,7 +2225,7 @@ page.open(url, function(status) {
$(".entropy").val("012345").trigger("input"); $(".entropy").val("012345").trigger("input");
}); });
// check the entropy is shown to be the correct type // check the entropy is shown to be the correct type
waitForGenerate(function() { waitForEntropyFeedback(function() {
var entropyText = page.evaluate(function() { var entropyText = page.evaluate(function() {
return $(".entropy-container").text(); return $(".entropy-container").text();
}); });
@@ -2213,7 +2247,7 @@ page.open(url, function(status) {
$(".entropy").val("123456").trigger("input"); $(".entropy").val("123456").trigger("input");
}); });
// check the entropy is shown to be the correct type // check the entropy is shown to be the correct type
waitForGenerate(function() { waitForEntropyFeedback(function() {
var entropyText = page.evaluate(function() { var entropyText = page.evaluate(function() {
return $(".entropy-container").text(); return $(".entropy-container").text();
}); });
@@ -2235,7 +2269,7 @@ page.open(url, function(status) {
$(".entropy").val("789").trigger("input"); $(".entropy").val("789").trigger("input");
}); });
// check the entropy is shown to be the correct type // check the entropy is shown to be the correct type
waitForGenerate(function() { waitForEntropyFeedback(function() {
var entropyText = page.evaluate(function() { var entropyText = page.evaluate(function() {
return $(".entropy-container").text(); return $(".entropy-container").text();
}); });
@@ -2257,7 +2291,7 @@ page.open(url, function(status) {
$(".entropy").val("abcdef").trigger("input"); $(".entropy").val("abcdef").trigger("input");
}); });
// check the entropy is shown to be the correct type // check the entropy is shown to be the correct type
waitForGenerate(function() { waitForEntropyFeedback(function() {
var entropyText = page.evaluate(function() { var entropyText = page.evaluate(function() {
return $(".entropy-container").text(); return $(".entropy-container").text();
}); });
@@ -2279,7 +2313,7 @@ page.open(url, function(status) {
$(".entropy").val("123456").trigger("input"); $(".entropy").val("123456").trigger("input");
}); });
// check the entropy is shown as base 6, not as the original dice value // check the entropy is shown as base 6, not as the original dice value
waitForGenerate(function() { waitForEntropyFeedback(function() {
var entropyText = page.evaluate(function() { var entropyText = page.evaluate(function() {
return $(".entropy-container").text(); return $(".entropy-container").text();
}); });
@@ -2299,58 +2333,52 @@ page.open(url, function(status) {
// The number of bits of entropy accumulated is shown // The number of bits of entropy accumulated is shown
function() { function() {
page.open(url, function(status) { page.open(url, function(status) {
var tests = { //[ entropy, bits ]
"0000 0000 0000 0000 0000": "20", var tests = [
"0": "1", [ "0000 0000 0000 0000 0000", "20" ],
"0000": "4", [ "0", "1" ],
"6": "3", [ "0000", "4" ],
"7": "3", [ "6", "3" ],
"8": "4", [ "7", "3" ],
"F": "4", [ "8", "4" ],
"29": "5", [ "F", "4" ],
"0A": "8", [ "29", "5" ],
"1A": "8", // hex is always multiple of 4 bits of entropy [ "0A", "8" ],
"2A": "8", [ "1A", "8" ], // hex is always multiple of 4 bits of entropy
"4A": "8", [ "2A", "8" ],
"8A": "8", [ "4A", "8" ],
"FA": "8", [ "8A", "8" ],
"000A": "16", [ "FA", "8" ],
"2220": "10", [ "000A", "16" ],
"2221": "9", // uses dice, so entropy is actually 1110 [ "2220", "10" ],
"2227": "12", [ "2221", "9" ], // uses dice, so entropy is actually 1110
"222F": "16", [ "2227", "12" ],
"FFFF": "16", [ "222F", "16" ],
} [ "FFFF", "16" ],
// Arrange tests in array so last one can be easily detected ]
var entropys = [];
var results = [];
for (var entropy in tests) {
entropys.push(entropy);
results.push(tests[entropy]);
}
// use entropy // use entropy
page.evaluate(function(e) { page.evaluate(function(e) {
$(".use-entropy").prop("checked", true).trigger("change"); $(".use-entropy").prop("checked", true).trigger("change");
}); });
// Run each test // Run each test
var nextTest = function runNextTest(i) { var nextTest = function runNextTest(i) {
var entropy = entropys[i]; var entropy = tests[i][0];
var expected = results[i]; var expected = tests[i][1];
// set entropy // set entropy
page.evaluate(function(e) { page.evaluate(function(e) {
$(".addresses").empty(); // bit of a hack, but needed for waitForGenerate
$(".entropy").val(e).trigger("input"); $(".entropy").val(e).trigger("input");
}, entropy); }, entropy);
// check the number of bits of entropy is shown // check the number of bits of entropy is shown
waitForGenerate(function() { waitForEntropyFeedback(function() {
var entropyText = page.evaluate(function() { var entropyText = page.evaluate(function() {
return $(".entropy-container").text(); return $(".entropy-error").text();
}); });
if (entropyText.indexOf("Have " + expected + " bits of entropy") == -1) { if (entropyText.indexOf("Have " + expected + " bits of entropy") == -1) {
console.log("Accumulated entropy is not shown correctly for " + entropy); console.log("Accumulated entropy is not shown correctly for " + entropy);
console.log(entropyText);
fail(); fail();
} }
var isLastTest = i == results.length - 1; var isLastTest = i == tests.length - 1;
if (isLastTest) { if (isLastTest) {
next(); next();
} }
@@ -2372,7 +2400,7 @@ page.open(url, function(status) {
$(".entropy").val("7654321").trigger("input"); $(".entropy").val("7654321").trigger("input");
}); });
// check the amount of additional entropy required is shown // check the amount of additional entropy required is shown
waitForGenerate(function() { waitForEntropyFeedback(function() {
var entropyText = page.evaluate(function() { var entropyText = page.evaluate(function() {
return $(".entropy-container").text(); return $(".entropy-container").text();
}); });
@@ -2438,33 +2466,16 @@ page.open(url, function(status) {
test = tests[i]; test = tests[i];
page.evaluate(function(e) { page.evaluate(function(e) {
$(".addresses").empty(); $(".addresses").empty();
$(".phrase").val("");
$(".entropy").val(e).trigger("input"); $(".entropy").val(e).trigger("input");
}, test.entropy); }, test.entropy);
waitForGenerate(function() { if (test.words == 0) {
// check the strength of the current mnemonic
var mnemonic = page.evaluate(function() { var mnemonic = page.evaluate(function() {
return $(".phrase").val(); return $(".phrase").val();
}); });
if (test.words == 0) { if (mnemonic.length > 0) {
if (mnemonic.length > 0) { console.log("Mnemonic length for " + test.nextStrength + " strength is not " + test.words);
console.log("Mnemonic length for " + test.nextStrength + " strength is not " + test.words); console.log("Mnemonic: " + mnemonic);
console.log("Mnemonic: " + mnemonic);
fail();
}
}
else {
if (mnemonic.split(" ").length != test.words) {
console.log("Mnemonic length for " + test.nextStrength + " strength is not " + test.words);
console.log("Mnemonic: " + mnemonic);
fail();
}
}
// check the strength of the next mnemonic is shown
var entropyText = page.evaluate(function() {
return $(".entropy-container").text();
});
if (entropyText.indexOf("required to generate " + test.nextStrength + " mnemonic") == -1) {
console.log("Strength indicator for " + test.nextStrength + " mnemonic is incorrect");
fail(); fail();
} }
var isLastTest = i == tests.length - 1; var isLastTest = i == tests.length - 1;
@@ -2474,7 +2485,35 @@ page.open(url, function(status) {
else { else {
runNextTest(i+1); runNextTest(i+1);
} }
}); }
else {
waitForGenerate(function() {
// check the strength of the current mnemonic
var mnemonic = page.evaluate(function() {
return $(".phrase").val();
});
if (mnemonic.split(" ").length != test.words) {
console.log("Mnemonic length for " + test.nextStrength + " strength is not " + test.words);
console.log("Mnemonic: " + mnemonic);
fail();
}
// check the strength of the next mnemonic is shown
var entropyText = page.evaluate(function() {
return $(".entropy-container").text();
});
if (entropyText.indexOf("required to generate " + test.nextStrength + " mnemonic") == -1) {
console.log("Strength indicator for " + test.nextStrength + " mnemonic is incorrect");
fail();
}
var isLastTest = i == tests.length - 1;
if (isLastTest) {
next();
}
else {
runNextTest(i+1);
}
});
}
} }
nextTest(0); nextTest(0);
}); });
@@ -2567,6 +2606,45 @@ page.open(url, function(status) {
}); });
}, },
// Blank entropy does not generate mnemonic or addresses
function() {
page.open(url, function(status) {
// use entropy
page.evaluate(function() {
$(".use-entropy").prop("checked", true).trigger("change");
$(".entropy").val("").trigger("input");
});
waitForFeedback(function() {
// check there is no mnemonic
var phrase = page.evaluate(function() {
return $(".phrase").val();
});
if (phrase != "") {
console.log("Blank entropy does not result in blank mnemonic");
console.log("Got: " + phrase);
fail();
}
// check there are no addresses displayed
var addresses = page.evaluate(function() {
return $(".address").length;
});
if (addresses != 0) {
console.log("Blank entropy does not result in zero addresses");
fail();
}
// Check the feedback says 'blank entropy'
var feedback = page.evaluate(function() {
return $(".feedback").text();
});
if (feedback != "Blank entropy") {
console.log("Blank entropy does not show feedback message");
fail();
}
next();
});
});
},
// If you wish to add more tests, do so here... // If you wish to add more tests, do so here...
// Here is a blank test template // Here is a blank test template