187 lines
6.4 KiB
Vue
187 lines
6.4 KiB
Vue
<script setup lang="ts">
|
|
let { data: challengeData } = await useFetch('/api/pow/challenge');
|
|
let { data: powData } = await useFetch('/api/pow');
|
|
|
|
if (!challengeData || !powData) {
|
|
throw createError({
|
|
statusCode: 500,
|
|
message: 'Failed to fetch data',
|
|
});
|
|
}
|
|
|
|
const algorithms = {
|
|
"argon2": {
|
|
name: 'argon2',
|
|
label: 'Argon2',
|
|
strategies: ['leading_zeroes', 'target_number'],
|
|
},
|
|
"kctf": {
|
|
name: 'kctf',
|
|
label: 'kCTF',
|
|
strategies: ['null'],
|
|
},
|
|
"sha256": {
|
|
name: 'sha256',
|
|
label: 'SHA256',
|
|
strategies: ['leading_zeroes', 'target_number'],
|
|
},
|
|
};
|
|
|
|
async function refresh() {
|
|
challengeData.value = await $fetch('/api/pow/challenge');
|
|
powData.value = await $fetch('/api/pow');
|
|
|
|
resetCaptcha();
|
|
}
|
|
|
|
function resetCaptcha() {
|
|
document.querySelector("pow-captcha")!.dispatchEvent(new CustomEvent('reset', {
|
|
detail: {
|
|
challenge: challengeData.value.challenge,
|
|
}
|
|
}));
|
|
}
|
|
|
|
let bench_results = ref([])
|
|
let start = ref(0);
|
|
let continue_bench: Promise<void> | null = null;
|
|
|
|
async function bench() {
|
|
for (let algorithm_name in algorithms) {
|
|
let algorithm = algorithms[algorithm_name as "sha256" | "argon2" | "kctf"];
|
|
for (let strategy of algorithm.strategies) {
|
|
for (let i = 1; i <= 3; i++) {
|
|
// reduce statistical anomolies by running tests multiple times and averaging after tha fact
|
|
for (let j = 0; j < 5; j++) {
|
|
let difficulty;
|
|
switch (strategy) {
|
|
case 'leading_zeroes':
|
|
difficulty = i;
|
|
break;
|
|
case 'null':
|
|
case 'target_number':
|
|
// these tests scale linearly, so to try to match the
|
|
// complexity of leading_zeroes, we grow the difficulty
|
|
// exponentially
|
|
difficulty = Math.pow(16, i);
|
|
break;
|
|
}
|
|
await changeAlgorithm(algorithm_name);
|
|
if (strategy !== 'null') {
|
|
await changeStrategy(strategy);
|
|
}
|
|
await $fetch('/api/pow/difficulty', {
|
|
method: 'PUT',
|
|
body: JSON.stringify({
|
|
difficulty: difficulty,
|
|
}),
|
|
})
|
|
|
|
// sleep for 300ms
|
|
await new Promise((resolve) => setTimeout(resolve, 750));
|
|
|
|
await refresh();
|
|
|
|
continue_bench = new Promise((resolve) => {
|
|
document.querySelector("pow-captcha")!.addEventListener('impost:solved', () => {
|
|
resolve();
|
|
});
|
|
});
|
|
start.value = performance.now();
|
|
document.querySelector("pow-captcha")!.dispatchEvent(new Event('solve'));
|
|
await continue_bench;
|
|
let end = performance.now();
|
|
const data = {
|
|
algorithm: algorithm_name,
|
|
cores: navigator.hardwareConcurrency,
|
|
strategy: strategy,
|
|
difficulty: difficulty,
|
|
time: end - start.value,
|
|
};
|
|
|
|
const should_scroll = document.documentElement.scrollTop + document.documentElement.clientHeight >= document.documentElement.scrollHeight;
|
|
bench_results.value.push(data);
|
|
if (should_scroll) {
|
|
document.documentElement.scrollTop = document.documentElement.scrollHeight;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function solved(ev: CustomEvent) {
|
|
console.log("Solved:", ev.detail.solution);
|
|
}
|
|
|
|
async function changeAlgorithmEV(ev: Event) {
|
|
changeAlgorithm(ev.target.value);
|
|
|
|
refresh();
|
|
}
|
|
|
|
async function changeAlgorithm(algorithm: string) {
|
|
await $fetch('/api/pow/algorithm', {
|
|
method: 'PUT',
|
|
body: JSON.stringify({
|
|
algorithm: algorithm
|
|
}),
|
|
});
|
|
}
|
|
|
|
async function changeStrategyEV(ev: Event) {
|
|
changeStrategy(ev.target.value);
|
|
|
|
refresh();
|
|
}
|
|
|
|
async function changeStrategy(strategy: string) {
|
|
await $fetch('/api/pow/strategy', {
|
|
method: 'PUT',
|
|
body: JSON.stringify({
|
|
strategy: strategy
|
|
}),
|
|
});
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<pow-captcha challengeUrl="/api/pow" :challengejson="JSON.stringify(challengeData!.challenge)"
|
|
@impost:solved="solved" />
|
|
<div class="flex flex-row gap-4">
|
|
<div class="flex flex-row gap-2" v-for="algorithm in algorithms" :key="algorithm.label">
|
|
<input type="radio" name="algorithm" @change="changeAlgorithmEV" :value="algorithm.name"
|
|
:id="algorithm.name" :checked="powData!.algorithm === algorithm.name"> <label :for="algorithm.name">{{
|
|
algorithm.label
|
|
}}</label>
|
|
</div>
|
|
</div>
|
|
<div v-if="algorithms[powData!.algorithm].strategies.length > 1 && powData!.algorithm === algorithms[powData!.algorithm].name"
|
|
class="flex flex-row gap-4">
|
|
<div class="flex flex-row gap-2" v-for="strategy in algorithms[powData!.algorithm].strategies">
|
|
<input type="radio" name="strategy" @change="changeStrategyEV" :value="strategy" :id="strategy"
|
|
:checked="powData!.strategy === strategy"> <label :for="strategy">{{ strategy }}</label>
|
|
</div>
|
|
</div>
|
|
<input type="button" value="Start benchmark" @click="bench" />
|
|
<div v-if="bench_results.length > 0">
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Algorithm</th>
|
|
<th>Strategy</th>
|
|
<th>Difficulty</th>
|
|
<th>Time (ms)</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr v-for="result in bench_results" :key="result.algorithm + result.strategy + result.difficulty">
|
|
<td>{{ algorithms[result.algorithm].label }}</td>
|
|
<td>{{ result.strategy }}</td>
|
|
<td>{{ result.difficulty }}</td>
|
|
<td>{{ result.time }}</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</template> |