Display time to reach 50% probability

This commit is contained in:
Boris Kubiak 2021-11-23 17:41:48 +01:00
parent 620a2c1980
commit 14b39f82ae
5 changed files with 435 additions and 16188 deletions

1
.husky/.gitignore vendored
View file

@ -1 +0,0 @@
_

16486
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -20,6 +20,7 @@
"core-js": "^3.6.5",
"crypto-js": "^3.3.0",
"downloadjs": "^1.4.7",
"humanize-duration": "^3.27.0",
"keccak": "^3.0.1",
"randombytes": "^2.0.6",
"register-service-worker": "^1.7.1",
@ -37,7 +38,7 @@
"cross-env": "^7.0.3",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^6.2.2",
"husky": "^6.0.0",
"husky": "^7.0.0",
"prettier": "^2.2.1",
"pretty-quick": "^3.1.0",
"sass": "^1.26.5",

View file

@ -1,28 +1,38 @@
<template>
<div class="panel" id="input-panel">
<form :class="{error: inputError}" @submit.prevent="startGen">
<form :class="{ error: inputError }" @submit.prevent="startGen">
<div class="error-text">Numbers and letters from A to F only</div>
<input type="text" class="text-input-large" id="input"
:placeholder="suffix ? 'Suffix' : 'Prefix'" v-model="hex" :disabled="running">
<input
type="text"
class="text-input-large"
id="input"
:placeholder="suffix ? 'Suffix' : 'Prefix'"
v-model="hex"
:disabled="running"
/>
<div class="row justify-content-center hide-render">
<div class="spinner">
<div></div><div></div><div></div><div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</div>
<div class="example hide-prerender">
E.g.&nbsp;
<span class="monospace">
0x<!--
--><b v-if="!suffix" v-text="example.chosen"></b><!--
--><span v-text="example.random"></span><!--
--><b v-if="!suffix" v-text="example.chosen"></b
><!--
--><span v-text="example.random"></span
><!--
--><b v-if="suffix" v-text="example.chosen"></b>
</span>
</div>
<div class="row controls hide-prerender">
<div class="col-12 col-sm-6 col-md-12 col-lg-6">
<label class="checkbox">
<input type="checkbox" name="checkbox" checked="" v-model="checksum"
:disabled="running">
<input type="checkbox" name="checkbox" checked="" v-model="checksum" :disabled="running" />
<i class="left"> </i>
Case-sensitive
</label>
@ -30,29 +40,44 @@
<div class="col-12 col-sm-6 col-md-12 col-lg-6">
<span>Prefix</span>
<label class="switch">
<input type="checkbox" v-model="suffix" :disabled="running">
<input type="checkbox" v-model="suffix" :disabled="running" />
<span class="slider"></span>
</label>
<span>Suffix</span>
</div>
</div>
<div class="threads hide-prerender">
<input type="button" class="square-btn button-large" value="-" @click="threads--"
:disabled="running || threads <= 1">
<input type="button" class="square-btn arrow button-large" value="+" @click="threads++"
:disabled="running">
<input
type="button"
class="square-btn button-large"
value="-"
@click="threads--"
:disabled="running || threads <= 1"
/>
<input
type="button"
class="square-btn arrow button-large"
value="+"
@click="threads++"
:disabled="running"
/>
<h4 v-text="threads"></h4>
<span>threads</span>
<span>&nbsp;threads</span>
<span v-if="threads === cores">(recommended)</span>
</div>
<div class="row">
<div class="col-lg-6 col-sm-12">
<input type="button" value="Generate" class="button-large hide-render" disabled>
<input type="button" value="Generate" class="button-large hide-prerender" @click="startGen"
:disabled="running || inputError || error">
<input type="button" value="Generate" class="button-large hide-render" disabled />
<input
type="button"
value="Generate"
class="button-large hide-prerender"
@click="startGen"
:disabled="running || inputError || error"
/>
</div>
<div class="col-lg-6 col-sm-12">
<input type="button" value="Stop" class="button-large" @click="stopGen" :disabled="!running">
<input type="button" value="Stop" class="button-large" @click="stopGen" :disabled="!running" />
</div>
</div>
</form>
@ -75,7 +100,7 @@
export default {
props: {
running: Boolean,
cores: Number
cores: Number,
},
data: function () {
return {
@ -83,7 +108,7 @@
hex: '',
checksum: true,
suffix: false,
error: false
error: false,
};
},
computed: {
@ -97,10 +122,10 @@
const chosen = this.checksum ? this.hex : mixCase(this.hex);
let random = '';
for (let i = 0; i < 40 - this.hex.length; i++) {
random += mixCase(Math.floor((Math.random() * 16)).toString(16));
random += mixCase(Math.floor(Math.random() * 16).toString(16));
}
return {random, chosen};
}
return { random, chosen };
},
},
methods: {
startGen: function () {
@ -110,7 +135,7 @@
},
stopGen: function () {
this.$emit('stop');
}
},
},
watch: {
hex: function () {
@ -124,8 +149,8 @@
},
threads: function () {
this.$emit('input-change', 'threads', this.threads);
}
}
},
},
};
</script>

View file

@ -1,10 +1,13 @@
<template>
<div class="panel">
<div>Difficulty: <span class="output" v-text="formatNum(difficulty)">1</span></div>
<div>Generated: <span class="output"
v-text="formatNum(count) + (count === 1 ? ' address' : ' addresses')">0 addresses</span>
<div>
Generated:
<span class="output" v-text="formatNum(count) + (count === 1 ? ' address' : ' addresses')"
>0 addresses</span
>
</div>
<div>50% probability: <span class="output" v-text="probability50">0 addresses</span></div>
<div>50% probability: <span class="output" v-text="speed ? time50 : adresses50">0 addresses</span></div>
<div>Speed: <span class="output" v-text="speed + ' addr/s'">0 addr/s</span></div>
<div>Status: <span class="output" v-text="status">Waiting</span></div>
@ -20,27 +23,33 @@
</template>
<script>
import humanizeDuration from 'humanize-duration';
const computeDifficulty = function (pattern, isChecksum) {
const ret = Math.pow(16, pattern.length);
return isChecksum ? (ret * Math.pow(2, pattern.replace(/[^a-f]/gi, '').length)) : ret;
return isChecksum ? ret * Math.pow(2, pattern.replace(/[^a-f]/gi, '').length) : ret;
};
const computeProbability = function (difficulty, attempts) {
return 1 - Math.pow(1 - (1 / difficulty), attempts);
return 1 - Math.pow(1 - 1 / difficulty, attempts);
};
const isValidHex = function (hex) {
return hex.length ? /^[0-9A-F]+$/g.test(hex.toUpperCase()) : true;
};
export default {
data: function () {
return {
speed: 0,
count: 0
count: 0,
};
},
props: {
hex: String,
checksum: Boolean,
status: String,
firstTick: {}
firstTick: {},
},
watch: {
hex() {
@ -48,32 +57,47 @@
},
checksum() {
this.count = 0;
}
},
},
computed: {
inputError: function () {
return !isValidHex(this.hex);
},
difficulty: function () {
return this.inputError ? 'N/A' : computeDifficulty(this.hex, this.checksum);
},
probability50: function () {
return this.inputError ? 'N/A' : this.formatNum(Math.floor(Math.log(0.5) / Math.log(1 - (1 / this.difficulty)))) + ' addresses';
probability50() {
return this.inputError ? 0 : Math.floor(Math.log(0.5) / Math.log(1 - 1 / this.difficulty));
},
adresses50: function () {
if (this.probability50 === -Infinity) {
return 'Nearly impossible';
}
return this.inputError ? 'N/A' : this.formatNum(this.probability50) + ' addresses';
},
time50: function () {
const seconds = this.probability50 / this.speed;
if (seconds > 200 * 365.25 * 24 * 3600 || seconds === -Infinity) {
return 'Thousands of years';
}
return this.inputError ? 'N/A' : humanizeDuration(Math.round(seconds) * 1000, { largest: 2 });
},
probability: function () {
return Math.round(10000 * computeProbability(this.difficulty, this.count)) / 100;
}
},
},
methods: {
formatNum: function (num) {
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ' ');
}
},
},
created: function () {
this.$parent.$on('increment-counter', (incr) => {
this.count += (incr > 0 ? incr : -this.count);
this.speed = incr > 0 ? Math.floor(1000 * this.count / (performance.now() - this.firstTick)) : 0;
this.count += incr > 0 ? incr : -this.count;
this.speed = incr > 0 ? Math.floor((1000 * this.count) / (performance.now() - this.firstTick)) : 0;
});
}
},
};
</script>
<style lang="sass" scoped>