Initial commit

Once again a weird place to commit, I have already done a lot of work, but I am just bad at using git, okay.
This commit is contained in:
Zoe
2025-11-17 16:12:26 +00:00
commit cfab3d0b8f
58 changed files with 18689 additions and 0 deletions

View File

@@ -0,0 +1,6 @@
const adjectives = ['swift', 'silent', 'hidden', 'clever', 'brave', 'sharp', 'shadow', 'crimson', 'bright', 'quiet', 'loud', 'happy', 'dark', 'evil', 'good', 'intelligent', 'lovely', 'mysterious', 'peaceful', 'powerful', 'pure', 'quiet', 'shiny', 'sleepy', 'strong', 'sweet', 'tall', 'warm', 'gentle', 'kind', 'nice', 'polite', 'rough', 'rude', 'scary', 'shy', 'silly', 'smart', 'strange', 'tough', 'ugly', 'vivid', 'wicked', 'wise', 'young', 'sleepy'];
const nouns = ['fox', 'river', 'stone', 'cipher', 'link', 'comet', 'falcon', 'signal', 'anchor', 'spark', 'stone', 'comet', 'rocket', 'snake', 'snail', 'shark', 'elephant', 'cat', 'dog', 'whale', 'orca', 'cactus', 'flower', 'frog', 'toad', 'apple', 'strawberry', 'raspberry', 'lemon', 'bot', 'gopher', 'dinosaur', 'racoon', 'penguin', 'chameleon', 'atom', 'particle', 'witch', 'wizard', 'warlock', 'deer']
export function getWorkerName() {
return `${adjectives[Math.floor(Math.random() * adjectives.length)]}-${nouns[Math.floor(Math.random() * nouns.length)]}`;
}

View File

@@ -0,0 +1,170 @@
// This worker just sits on another thread and waits for message to solve
// challenges so that we dont block the render thread
import {
type WorkerRequest,
type SolutionMessage,
WorkerMessageType,
WorkerResponseType,
ChallengeStrategy,
} from "~/types/pow";
const worker_name = getWorkerName();
let solver: SolverModule | null = null;
let atomic_nonce: Int32Array | null = null;
let atomic_solution: Int32Array | null = null;
async function loadWasmSolver(module: WebAssembly.Module) {
if (atomic_nonce === null || atomic_solution === null) {
throw createError("Atomics not initialized");
}
console.debug(`[${worker_name}]: Loading WASM solver`);
solver = await WebAssembly.instantiate(module, {
env: {
__get_solution: () => Atomics.load(atomic_solution!, 0),
__set_solution: (value: number) => Atomics.store(atomic_solution!, 0, value),
__cmpxchg_solution: (expected: number, replacement: number) => Atomics.compareExchange(atomic_solution!, 0, expected, replacement),
__fetch_add_nonce: (value: number) => Atomics.add(atomic_nonce!, 0, value),
__log: (ptr: number, len: number) => {
const string_data = new Uint8Array(solver!.exports.memory.buffer, ptr, len);
console.log(`[${worker_name}]: ${new TextDecoder().decode(string_data)}`);
},
}
}) as unknown as SolverModule;
console.debug(`[${worker_name}]: WASM solver loaded`);
}
onmessage = async (event: MessageEvent<WorkerRequest>) => {
if (event.data.type === WorkerMessageType.Init) {
console.log(`[${worker_name}]: Initializing...`);
atomic_nonce = new Int32Array(event.data.sab, 0, 1);
atomic_solution = new Int32Array(event.data.sab, 4, 1);
try {
await loadWasmSolver(event.data.module);
} catch (error: any) {
console.error(`[${worker_name}]: Failed to load WASM solver:`, error);
postMessage({
type: WorkerResponseType.Error,
error: `Could not load WASM solver: ${error.message}`,
} as SolutionMessage);
return;
}
if (!solver) {
console.error(`[${worker_name}]: Failed to load WASM solver`);
postMessage({
type: WorkerResponseType.Error,
error: "Failed to load WASM solver",
} as SolutionMessage);
return;
}
postMessage({
type: WorkerResponseType.Ok,
} as SolutionMessage);
return;
}
if (!solver) {
postMessage({
type: WorkerResponseType.Error,
error: "WASM solver not loaded",
} as SolutionMessage);
return;
}
const { strategy } = event.data;
const encoder = new TextEncoder();
let solution: number;
let target: string = event.data.target;
let target_bytes, target_ptr;
let memory;
switch (strategy) {
case ChallengeStrategy.LeadingZeroes:
const { difficulty } = event.data;
console.debug(`[${worker_name}]: recieved ${strategy} challenge: ${target}, difficulty: ${difficulty}`);
target_bytes = encoder.encode(target);
target_ptr = solver.exports.malloc(target_bytes.length);
if (target_ptr === 0 || target_ptr === null) {
console.error(`[${worker_name}]: Failed to allocate memory for challenge string`);
postMessage({
type: WorkerResponseType.Error,
error: "Failed to allocate memory for challenge string",
} as SolutionMessage);
return;
}
memory = new Uint8Array(solver.exports.memory.buffer);
memory.set(target_bytes, target_ptr);
solution = solver.exports.solve_leaading_zeroes_challenge(
target_ptr,
target.length,
difficulty,
);
console.debug(`[${worker_name}]: WASM solver found nonce: ${solution}`);
break;
case ChallengeStrategy.TargetNumber:
const { salt } = event.data;
console.debug(`[${worker_name}]: recieved ${strategy} challenge: ${target}, salt: ${salt}`);
const salt_bytes = encoder.encode(salt);
target_bytes = encoder.encode(target);
const salt_ptr = solver.exports.malloc(salt_bytes.length);
if (salt_ptr === 0 || salt_ptr === null) {
console.error(`[${worker_name}]: Failed to allocate memory for salt string`);
postMessage({
type: WorkerResponseType.Error,
error: "Failed to allocate memory for salt string",
} as SolutionMessage);
return;
}
target_ptr = solver.exports.malloc(target_bytes.length);
if (target_ptr === 0 || target_ptr === null) {
console.error(`[${worker_name}]: Failed to allocate memory for target string`);
postMessage({
type: WorkerResponseType.Error,
error: "Failed to allocate memory for target string",
} as SolutionMessage);
return;
}
memory = new Uint8Array(solver.exports.memory.buffer);
memory.set(salt_bytes, salt_ptr);
memory.set(target_bytes, target_ptr);
solution = solver.exports.solve_target_number_challenge(
target_ptr,
target_bytes.length,
salt_ptr,
salt_bytes.length,
);
console.debug(`[${worker_name}]: WASM solver found nonce: ${solution}`);
break;
}
// we are just assuming that if its less than -1, its the min i32
if (solution < 0) {
return postMessage({
type: WorkerResponseType.Error,
error: "failed to solve challenge",
} as SolutionMessage);
}
postMessage({
type: WorkerResponseType.Solution,
nonce: solution === -1 ? null : solution.toString()
} as SolutionMessage);
};