Compare commits
2 Commits
8d4edd43bf
...
c3f13cc6e3
Author | SHA1 | Date | |
---|---|---|---|
c3f13cc6e3 | |||
dd829b203d |
@ -20,5 +20,13 @@ export default defineConfig({
|
||||
},
|
||||
},
|
||||
plugins: [tsconfigPaths()],
|
||||
build: {
|
||||
rollupOptions: {
|
||||
output: {
|
||||
assetFileNames: "assets/[name].[ext]", // Ensure .wasm files are copied
|
||||
},
|
||||
},
|
||||
},
|
||||
assetsInclude: ["**/*.wasm"],
|
||||
},
|
||||
});
|
||||
|
BIN
packages/frontend/bun.lockb
Executable file
BIN
packages/frontend/bun.lockb
Executable file
Binary file not shown.
@ -1,23 +1,25 @@
|
||||
{
|
||||
"name": "frontend",
|
||||
"type": "module",
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"dev": "astro dev",
|
||||
"build": "astro build",
|
||||
"preview": "astro preview",
|
||||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/tailwind": "^6.0.2",
|
||||
"astro": "^5.5.5",
|
||||
"autoprefixer": "^10.4.21",
|
||||
"pg": "^8.11.11",
|
||||
"postcss": "^8.5.3",
|
||||
"tailwindcss": "^3.0.24",
|
||||
"vite-tsconfig-paths": "^5.1.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/pg": "^8.11.11"
|
||||
}
|
||||
"name": "frontend",
|
||||
"type": "module",
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"dev": "astro dev",
|
||||
"build": "astro build",
|
||||
"preview": "astro preview",
|
||||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/tailwind": "^6.0.2",
|
||||
"argon2id": "^1.0.1",
|
||||
"astro": "^5.5.5",
|
||||
"autoprefixer": "^10.4.21",
|
||||
"pg": "^8.11.11",
|
||||
"postcss": "^8.5.3",
|
||||
"tailwindcss": "^3.0.24",
|
||||
"vite-tsconfig-paths": "^5.1.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-wasm": "^6.2.2",
|
||||
"@types/pg": "^8.11.11"
|
||||
}
|
||||
}
|
||||
|
BIN
packages/frontend/public/no-simd.wasm
Executable file
BIN
packages/frontend/public/no-simd.wasm
Executable file
Binary file not shown.
BIN
packages/frontend/public/simd.wasm
Executable file
BIN
packages/frontend/public/simd.wasm
Executable file
Binary file not shown.
230
packages/frontend/src/components/Argon2idTester.svelte
Normal file
230
packages/frontend/src/components/Argon2idTester.svelte
Normal file
@ -0,0 +1,230 @@
|
||||
<script lang="ts">
|
||||
import { type computeHash } from "argon2id";
|
||||
import setupWasm from "argon2id/lib/setup.js";
|
||||
|
||||
let totalHashes = 0;
|
||||
let argon2id: null | computeHash = null;
|
||||
let memorySize = 2560;
|
||||
let passes = 1;
|
||||
|
||||
function startsWithZeros(uint8Array: Uint8Array, numZeros: number) {
|
||||
if (numZeros > uint8Array.length * 8) {
|
||||
return false; // More zeros requested than possible in the array
|
||||
}
|
||||
|
||||
let zeroCount = 0;
|
||||
for (let i = 0; i < uint8Array.length; i++) {
|
||||
const byte = uint8Array[i];
|
||||
for (let j = 7; j >= 0; j--) {
|
||||
if ((byte >> j) & 1) {
|
||||
// Found a '1' bit, so the leading zeros sequence ends
|
||||
return zeroCount >= numZeros;
|
||||
}
|
||||
zeroCount++;
|
||||
if (zeroCount === numZeros) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reached the end of the array and the required number of zeros were found
|
||||
return zeroCount >= numZeros;
|
||||
}
|
||||
|
||||
async function init() {
|
||||
const SIMD_FILENAME = "/simd.wasm";
|
||||
const NON_SIMD_FILENAME = "/non-simd.wasm";
|
||||
|
||||
const setupWasmWithFetch = async (
|
||||
wasmUrl: string,
|
||||
importObject: WebAssembly.Imports
|
||||
): Promise<WebAssembly.WebAssemblyInstantiatedSource> => {
|
||||
try {
|
||||
const response = await fetch(wasmUrl);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to fetch WASM module from ${wasmUrl}: ${response.status}`);
|
||||
}
|
||||
const wasmBytes = await response.arrayBuffer();
|
||||
const result = await WebAssembly.instantiate(wasmBytes, importObject);
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.error(`Error initializing WASM from ${wasmUrl}:`, error);
|
||||
throw error; // Re-throw the error to be caught by the caller
|
||||
}
|
||||
};
|
||||
|
||||
argon2id = await setupWasm(
|
||||
(importObject) => setupWasmWithFetch(SIMD_FILENAME, importObject),
|
||||
(importObject) => setupWasmWithFetch(NON_SIMD_FILENAME, importObject)
|
||||
);
|
||||
}
|
||||
|
||||
// Simple PoW function (very basic for demonstration)
|
||||
async function proofOfWork(message: string, difficulty: number) {
|
||||
if (argon2id === null) {
|
||||
await init();
|
||||
}
|
||||
let nonce = 0;
|
||||
const h = argon2id!;
|
||||
while (true) {
|
||||
const p = new TextEncoder().encode(`${message}-${nonce}`);
|
||||
const hash = h({
|
||||
password: new Uint8Array(p),
|
||||
salt: crypto.getRandomValues(new Uint8Array(32)),
|
||||
memorySize: memorySize,
|
||||
parallelism: 1,
|
||||
passes: passes,
|
||||
tagLength: 32,
|
||||
});
|
||||
totalHashes++;
|
||||
if (startsWithZeros(hash, difficulty)) {
|
||||
return nonce;
|
||||
}
|
||||
nonce++;
|
||||
if (nonce > 100000) {
|
||||
throw new Error(
|
||||
"Could not find a valid nonce within a reasonable number of attempts. Try a lower difficulty."
|
||||
);
|
||||
}
|
||||
await new Promise((resolve) => setTimeout(resolve, 0)); // Yield control for responsiveness
|
||||
}
|
||||
}
|
||||
const challenge = "challenge";
|
||||
let difficulty = 4;
|
||||
let tries = 10;
|
||||
let solution = "";
|
||||
let isSolving = false;
|
||||
let errorMessage = "";
|
||||
let solveTime = "";
|
||||
|
||||
async function solveChallenge() {
|
||||
totalHashes = 0;
|
||||
isSolving = true;
|
||||
errorMessage = "";
|
||||
solution = "";
|
||||
solveTime = "";
|
||||
const startTime = performance.now();
|
||||
|
||||
try {
|
||||
const flooredDifficulty = Math.floor(difficulty);
|
||||
const percentage = difficulty - flooredDifficulty;
|
||||
const numberOfHiggerDifficultyTries = Math.floor(tries * percentage);
|
||||
const numberOfLowerDifficultyTries = tries - numberOfHiggerDifficultyTries;
|
||||
for (let i = 0; i < numberOfLowerDifficultyTries; i++) {
|
||||
const nonce = await proofOfWork(challenge, flooredDifficulty);
|
||||
solution = `${challenge}-${nonce}`;
|
||||
}
|
||||
for (let i = 0; i < numberOfHiggerDifficultyTries; i++) {
|
||||
const nonce = await proofOfWork(challenge, flooredDifficulty + 1);
|
||||
solution = `${challenge}-${nonce}`;
|
||||
}
|
||||
const endTime = performance.now();
|
||||
solveTime = (endTime - startTime).toFixed(2);
|
||||
} catch (error) {
|
||||
console.error("Error solving challenge:", error);
|
||||
const e = error as Error;
|
||||
errorMessage = e.message || "An error occurred while solving the challenge.";
|
||||
} finally {
|
||||
isSolving = false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="bg-gray-100 dark:bg-gray-800 p-6 rounded-md shadow-md mb-6 mt-8 lg:w-1/2 xl:w-1/3 mx-auto">
|
||||
<h2 class="text-xl font-bold mb-4 text-gray-800 dark:text-gray-200">The Challenge</h2>
|
||||
|
||||
<div class="mb-4">
|
||||
<label for="difficulty" class="block text-gray-700 dark:text-gray-300 text-sm font-bold mb-2">Memory:</label
|
||||
>
|
||||
<input
|
||||
type="number"
|
||||
id="memorySize"
|
||||
bind:value={memorySize}
|
||||
min="8"
|
||||
step="64"
|
||||
class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 dark:text-gray-300 leading-tight focus:outline-none focus:shadow-outline dark:bg-gray-700 dark:border-gray-600"
|
||||
placeholder="Number of leading zeros"
|
||||
/>
|
||||
<p class="text-gray-500 dark:text-gray-400 text-xs italic">Memory cost (KiB) in argon2id config.</p>
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<label for="difficulty" class="block text-gray-700 dark:text-gray-300 text-sm font-bold mb-2">Passes:</label
|
||||
>
|
||||
<input
|
||||
type="number"
|
||||
id="passes"
|
||||
bind:value={passes}
|
||||
min="1"
|
||||
step="1"
|
||||
class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 dark:text-gray-300 leading-tight focus:outline-none focus:shadow-outline dark:bg-gray-700 dark:border-gray-600"
|
||||
placeholder="Number of leading zeros"
|
||||
/>
|
||||
<p class="text-gray-500 dark:text-gray-400 text-xs italic">Number of passes in argon2id config.</p>
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<label for="difficulty" class="block text-gray-700 dark:text-gray-300 text-sm font-bold mb-2">Difficulty:</label
|
||||
>
|
||||
<input
|
||||
type="number"
|
||||
id="difficulty"
|
||||
bind:value={difficulty}
|
||||
min="0"
|
||||
step="1"
|
||||
class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 dark:text-gray-300 leading-tight focus:outline-none focus:shadow-outline dark:bg-gray-700 dark:border-gray-600"
|
||||
placeholder="Number of leading zeros"
|
||||
/>
|
||||
<p class="text-gray-500 dark:text-gray-400 text-xs italic">Higher difficulty requires more computation.</p>
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<label for="difficulty" class="block text-gray-700 dark:text-gray-300 text-sm font-bold mb-2">Tries:</label
|
||||
>
|
||||
<input
|
||||
type="number"
|
||||
id="tries"
|
||||
bind:value={tries}
|
||||
min="1"
|
||||
step="1"
|
||||
class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 dark:text-gray-300 leading-tight focus:outline-none focus:shadow-outline dark:bg-gray-700 dark:border-gray-600"
|
||||
placeholder="Number of leading zeros"
|
||||
/>
|
||||
<p class="text-gray-500 dark:text-gray-400 text-xs italic">The number of consecutive successes required to pass the verification.</p>
|
||||
</div>
|
||||
|
||||
<button
|
||||
on:click={solveChallenge}
|
||||
disabled={isSolving}
|
||||
class="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline disabled:bg-gray-500 disabled:cursor-not-allowed"
|
||||
>
|
||||
{#if isSolving}
|
||||
Solving...
|
||||
{:else}
|
||||
Solve Challenge
|
||||
{/if}
|
||||
</button>
|
||||
|
||||
{#if errorMessage}
|
||||
<p class="text-red-500 mt-2">{errorMessage}</p>
|
||||
{/if}
|
||||
|
||||
<p class="mt-3 text-sm text-gray-600 dark:text-gray-400">Total hashes calculated: {totalHashes}</p>
|
||||
|
||||
{#if solution}
|
||||
<div class="mt-6 p-4 bg-gray-200 dark:bg-gray-700 rounded-md">
|
||||
<h3 class="text-lg font-bold mb-2 text-gray-800 dark:text-gray-200">Solution Found!</h3>
|
||||
<p class="text-gray-700 dark:text-gray-300">
|
||||
The solution (challenge + nonce) is:
|
||||
<code class="bg-gray-300 dark:bg-gray-600 text-gray-900 dark:text-gray-100 p-1 rounded font-mono"
|
||||
>{solution}</code
|
||||
>
|
||||
</p>
|
||||
{#if solveTime}
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400 mt-1">
|
||||
Time to solve: {solveTime} ms
|
||||
</p>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
172
packages/frontend/src/components/VDFtester.svelte
Normal file
172
packages/frontend/src/components/VDFtester.svelte
Normal file
@ -0,0 +1,172 @@
|
||||
<script lang="ts">
|
||||
import { N_ARRAY } from "src/const"; // 假设你的常量文件现在导出 N_ARRAY
|
||||
|
||||
function generateRandomBigInt(min: bigint, max: bigint) {
|
||||
const range = max - min;
|
||||
const bitLength = range.toString(2).length;
|
||||
const byteLength = Math.ceil(bitLength / 8);
|
||||
const mask = (1n << BigInt(bitLength)) - 1n; // 用于截断的掩码
|
||||
let result;
|
||||
do {
|
||||
const randomBytes = new Uint8Array(byteLength);
|
||||
crypto.getRandomValues(randomBytes);
|
||||
result = 0n;
|
||||
for (let i = 0; i < byteLength; i++) {
|
||||
result = (result << 8n) | BigInt(randomBytes[i]);
|
||||
}
|
||||
result = result & mask; // 确保不超过 bitLength 位
|
||||
} while (result > range);
|
||||
return min + result;
|
||||
}
|
||||
|
||||
function generateValidG(N: bigint) {
|
||||
if (N <= 4n) throw new Error("N must be > 4");
|
||||
while (true) {
|
||||
const r = generateRandomBigInt(2n, N - 1n);
|
||||
const g = (r * r) % N;
|
||||
if (g !== 1n && g !== 0n && g !== N - 1n) {
|
||||
return g;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const workerContent = `addEventListener("message", async (event) => {
|
||||
const { g, N, difficulty } = event.data;
|
||||
function pow(base, exponent, mod) {
|
||||
let result = 1n;
|
||||
base = base % mod;
|
||||
while (exponent > 0n) {
|
||||
if (exponent % 2n === 1n) {
|
||||
result = (result * base) % mod;
|
||||
}
|
||||
base = (base * base) % mod;
|
||||
exponent = exponent / 2n;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
function computeVDFWithProgress(g, N, T, postProgress) {
|
||||
let result = g;
|
||||
for (let i = 0n; i < T; i++) {
|
||||
result = (result * result) % N;
|
||||
if (i % (T / 10000n) === 0n && T > 0n) {
|
||||
postProgress(Number(i * 100n) / Number(T));
|
||||
}
|
||||
}
|
||||
postProgress(100);
|
||||
return result;
|
||||
}
|
||||
const startTime = performance.now();
|
||||
const result = computeVDFWithProgress(g, N, difficulty, (progress) => {
|
||||
postMessage({ type: "progress", N: N.toString(), difficulty: difficulty.toString(), progress });
|
||||
});
|
||||
const endTime = performance.now();
|
||||
const timeTaken = endTime - startTime;
|
||||
postMessage({ type: "result", N: N.toString(), difficulty: difficulty.toString(), time: timeTaken, result });
|
||||
});
|
||||
`;
|
||||
|
||||
let isBenchmarking = false;
|
||||
interface BenchmarkResult {
|
||||
N: bigint;
|
||||
difficulty: bigint;
|
||||
time: number;
|
||||
}
|
||||
let benchmarkResults: BenchmarkResult[] = [];
|
||||
let currentProgress = 0;
|
||||
let currentN: bigint | null = null;
|
||||
let currentDifficulty: bigint | null = null;
|
||||
let worker: Worker | null = null;
|
||||
let currentTestIndex = 0;
|
||||
const difficulties = [BigInt(100000), BigInt(1000000)];
|
||||
const testCombinations: { N: bigint; difficulty: bigint }[] = [];
|
||||
|
||||
// 创建需要测试的 N 和难度的组合
|
||||
N_ARRAY.forEach(n => {
|
||||
difficulties.forEach(difficulty => {
|
||||
testCombinations.push({ N: n, difficulty });
|
||||
});
|
||||
});
|
||||
|
||||
async function startBenchmark() {
|
||||
if (testCombinations.length === 0) {
|
||||
alert("No N values provided in src/const N_ARRAY.");
|
||||
return;
|
||||
}
|
||||
isBenchmarking = true;
|
||||
benchmarkResults = [];
|
||||
currentTestIndex = 0;
|
||||
|
||||
const { N, difficulty } = testCombinations[currentTestIndex];
|
||||
const g = generateValidG(N);
|
||||
|
||||
let blob = new Blob([workerContent], { type: "text/javascript" });
|
||||
worker = new Worker(window.URL.createObjectURL(blob));
|
||||
|
||||
worker.onmessage = (event) => {
|
||||
const { type, N: resultNStr, difficulty: resultDifficultyStr, time, progress } = event.data;
|
||||
const resultN = BigInt(resultNStr);
|
||||
const resultDifficulty = BigInt(resultDifficultyStr);
|
||||
|
||||
if (type === "progress") {
|
||||
console.log(`N: ${resultN}, Difficulty: ${resultDifficulty}, Progress: ${progress}`);
|
||||
currentProgress = progress;
|
||||
currentN = resultN;
|
||||
currentDifficulty = resultDifficulty;
|
||||
} else if (type === "result") {
|
||||
benchmarkResults = [...benchmarkResults, { N: resultN, difficulty: resultDifficulty, time }];
|
||||
currentProgress = 0;
|
||||
currentN = null;
|
||||
currentDifficulty = null;
|
||||
currentTestIndex++;
|
||||
|
||||
if (currentTestIndex < testCombinations.length) {
|
||||
// 继续下一个测试组合
|
||||
const nextTest = testCombinations[currentTestIndex];
|
||||
const nextG = generateValidG(nextTest.N);
|
||||
worker?.postMessage({ g: nextG, N: nextTest.N, difficulty: nextTest.difficulty });
|
||||
} else {
|
||||
// 所有测试完毕
|
||||
isBenchmarking = false;
|
||||
worker?.terminate();
|
||||
worker = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 开始第一个测试
|
||||
worker.postMessage({ g, N, difficulty });
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="bg-zinc-50 dark:bg-zinc-800 p-6 rounded-md border dark:border-zinc-700 mb-6 mt-8 md:w-2/3 lg:w-1/2 xl:w-[37%] mx-8 md:mx-auto">
|
||||
<h2 class="text-xl font-bold mb-4 text-gray-800 dark:text-gray-200">VDF Benchmark</h2>
|
||||
|
||||
{#if !isBenchmarking}
|
||||
<button class="bg-blue-500 hover:bg-blue-600 duration-100 text-white font-bold py-2 px-4 rounded" on:click={startBenchmark}>
|
||||
Start Benchmark
|
||||
</button>
|
||||
{/if}
|
||||
|
||||
{#if isBenchmarking}
|
||||
<p class="mb-8 text-gray-700 dark:text-gray-300">Benchmarking in progress... ({currentTestIndex + 1}/{testCombinations.length})</p>
|
||||
{#if currentN !== null && currentDifficulty !== null}
|
||||
<p class="mb-2 text-gray-700 dark:text-gray-300">N Bits: {currentN.toString(2).length}</p>
|
||||
<p class="mb-2 text-gray-700 dark:text-gray-300">Difficulty: {currentDifficulty}</p>
|
||||
<div class="w-full bg-zinc-300 dark:bg-neutral-700 rounded-full h-1 relative overflow-hidden">
|
||||
<div class="bg-black dark:bg-white h-full rounded-full relative" style="width: {currentProgress}%">
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
{#if benchmarkResults.length > 0 && !isBenchmarking}
|
||||
<h3 class="text-lg font-bold mt-4 mb-2 text-gray-800 dark:text-gray-200">Benchmark Results</h3>
|
||||
<ul>
|
||||
{#each benchmarkResults as result}
|
||||
<li class="text-gray-700 dark:text-gray-300">
|
||||
N Bits: {result.N.toString(2).length}, Difficulty: {result.difficulty}, Time: {result.time.toFixed(2)} ms
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
{/if}
|
||||
</div>
|
13
packages/frontend/src/const.ts
Normal file
13
packages/frontend/src/const.ts
Normal file
@ -0,0 +1,13 @@
|
||||
const N_1024 = BigInt("129023318876534346704360951712586568674758913224876821534686030409476129469193481910786173836188085930974906857867802234113909470848523288588793477904039083513378341278558405407018889387577114155572311708428733260891448259786041525189132461448841652472631435226032063278124857443496954605482776113964107326943")
|
||||
|
||||
const N_2048 = BigInt("23987552118069940970878653610463005981599204778388399885550631951871084945075866571231062435627294546200946516668493107358732376187241747090707087544153108117326163500579370560400058549184722138636116585329496684877258304519458316233517215780035360354808658620079068489084797380781488445517430961701007542207001544091884001098497324624368085682074645221148086075871342544591022944384890014176612259729018968864426602901247715051556212559854689574013699665035317257438297910516976812428036717668766321871780963854649899276251822244719887233041422346429752896925499321431273560130952088238625622570366815755926694833109")
|
||||
|
||||
const N_1792 = BigInt("23987552118069940970878653610463005981599204778388399885550631951871084945075866571231062435627294546200946516668493107358732376187241747090707087544153108117326163500579370560400058549184722138636116585329496684877258304519458316233517215780035360354808658620079068489084797380781488445517430961701007542207001544091884001098497324624368085682074645221148086075871342544591022944384890014176612259729018968864426602901247715051556212559854689574013699665035317257438297910516976812428036717668766321871780963854649899276251822244719887233041422346429752896925499321431273560130952088238625622570366815755926694833109")
|
||||
|
||||
const N_1536 = BigInt("1694330250214463438908848400950857073137355630337290254958754184668036770489801447652464038218330711288158361242955860326168191830448553710492926795708495297280933502917598985378231124113971732841791156356676046934277122699383776036675381503510992810963611269045078440132744168908318454891211962146563551929591147663448816841024591820348784855441153716551049843185172472891407933214238000452095646085222944171689449292644270516031799660928056315886939284985905227")
|
||||
|
||||
const N_3072 = BigInt("4432919939296042464443862503456460073874727648022810391370558006281079088795179408238989283371442564716849343712703672836423961818025813387453469700639513190304802553045342607888612037304066433501317127429264242784608682213025490491212489901736408833027611579294436675682774458141490718959615677971745638214649336218217578937534746160749039668886450447773018369168258067682196337978245372237157696236362344796867228581553446331915147012787367438751646936429739232247148712001806846526947508445039707404287951727838234648917450736371192435665040644040487427986702098273581288935278964444790007953559851323281510927332862225214878776790605026472021669614552481167977412450477230442015077669503312683966631454347169703030544483487968842349634064181183599641180349414682042575010303056241481622837185325228233789954078775053744988023738762706404546546146837242590884760044438874357295029411988267287001033032827035809135092270843")
|
||||
|
||||
const N_4096 = BigInt("703671044356805218391078271512201582198770553281951369783674142891088501340774249238173262580562112786670043634665390581120113644316651934154746357220932310140476300088580654571796404198410555061275065442553506658401183560336140989074165998202690496991174269748740565700402715364422506782445179963440819952745241176450402011121226863984008975377353558155910994380700267903933205531681076494639818328879475919332604951949178075254600102192323286738973253864238076198710173840170988339024438220034106150475640983877458155141500313471699516670799821379238743709125064098477109094533426340852518505385314780319279862586851512004686798362431227795743253799490998475141728082088984359237540124375439664236138519644100625154580910233437864328111620708697941949936338367445851449766581651338876219676721272448769082914348242483068204896479076062102236087066428603930888978596966798402915747531679758905013008059396214343112694563043918465373870648649652122703709658068801764236979191262744515840224548957285182453209028157886219424802426566456408109642062498413592155064289314088837031184200671561102160059065729282902863248815224399131391716503171191977463328439766546574118092303414702384104112719959325482439604572518549918705623086363111")
|
||||
|
||||
export const N_ARRAY = [N_1024, N_1536, N_1792, N_2048, N_3072, N_4096];
|
8
packages/frontend/src/pages/test-vdf.astro
Normal file
8
packages/frontend/src/pages/test-vdf.astro
Normal file
@ -0,0 +1,8 @@
|
||||
---
|
||||
import VDFtester from "@components/VDFtester.svelte";
|
||||
import Layout from "@layouts/Layout.astro";
|
||||
---
|
||||
|
||||
<Layout>
|
||||
<VDFtester client:load />
|
||||
</Layout>
|
Loading…
Reference in New Issue
Block a user