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:
6
example-app/app/utils/worker-name.ts
Normal file
6
example-app/app/utils/worker-name.ts
Normal 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)]}`;
|
||||
}
|
||||
170
example-app/app/utils/worker.ts
Normal file
170
example-app/app/utils/worker.ts
Normal 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);
|
||||
};
|
||||
Reference in New Issue
Block a user