Files
impost/example-app/app/pages/bench.vue
2025-11-28 14:53:06 -06:00

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>