initial commit

This commit is contained in:
2026-05-14 18:38:09 +03:00
commit f41d64f39b
32 changed files with 1469 additions and 0 deletions
+3
View File
@@ -0,0 +1,3 @@
from .instance import Solver
__all__ = ['Solver']
Binary file not shown.
Binary file not shown.
+165
View File
@@ -0,0 +1,165 @@
import wasmtime
import struct
import math
import os
import ctypes
from pathlib import Path
class Solver:
def __init__(self):
"""Initialize the WASM solver"""
# Try to find the WASM file
current_dir = Path(__file__).parent
go_wasm_path = Path(__file__).parent.parent.parent / 'deepseek4free' / 'pkg' / 'solver' / 'sha3_wasm_bg.7b9ca65ddd.wasm'
if go_wasm_path.exists():
with open(go_wasm_path, 'rb') as f:
wasm_bytes = f.read()
else:
raise FileNotFoundError(f"WASM file not found at {go_wasm_path}")
engine = wasmtime.Engine()
self.module = wasmtime.Module(engine, wasm_bytes)
self.store = wasmtime.Store(engine)
self.linker = wasmtime.Linker(engine)
self.linker.define_wasi()
self.instance = self.linker.instantiate(self.store, self.module)
# Get exports - handle both old and new wasmtime-py API
exports = self.instance.exports(self.store)
# Get memory export
try:
# Try direct attribute access first
self.memory = exports.memory
except AttributeError:
# Try dict-like access
try:
self.memory = exports['memory']
except (KeyError, TypeError):
# Try get_export method
mem_extern = self.instance.get_export(self.store, 'memory')
if mem_extern and hasattr(mem_extern, 'memory'):
self.memory = mem_extern.memory
else:
raise RuntimeError("Could not find memory export in WASM module")
# Initialize functions - with error handling
try:
self.alloc_fn = exports.__wbindgen_export_0
except AttributeError:
self.alloc_fn = exports['__wbindgen_export_0']
try:
self.stack_ptr_fn = exports.__wbindgen_add_to_stack_pointer
except AttributeError:
self.stack_ptr_fn = exports['__wbindgen_add_to_stack_pointer']
try:
self.solve_fn = exports.wasm_solve
except AttributeError:
self.solve_fn = exports['wasm_solve']
def _write_to_memory(self, text: str) -> tuple[int, int]:
"""Write a string to WASM memory and return pointer and length"""
text_bytes = text.encode('utf-8')
length = len(text_bytes)
# Allocate memory - pass store as first argument
ptr = self.alloc_fn(self.store, length, 1)
print(f"[DEBUG] Allocated memory at ptr={ptr}, length={length}")
# Get memory data pointer
mem_ptr = self.memory.data_ptr(self.store)
print(f"[DEBUG] Memory pointer type: {type(mem_ptr)}")
# Write to memory - mem_ptr is a ctypes pointer, can index it directly
try:
for i, byte in enumerate(text_bytes):
mem_ptr[ptr + i] = byte
print(f"[DEBUG] Successfully wrote {length} bytes to memory")
except TypeError as e:
print(f"[DEBUG] Error writing to memory: {e}")
# Try alternative approach with ctypes address
try:
addr = ctypes.cast(mem_ptr, ctypes.c_void_p).value
print(f"[DEBUG] Memory address: {addr}")
buffer = (ctypes.c_ubyte * length).from_address(addr + ptr)
for i, byte in enumerate(text_bytes):
buffer[i] = byte
print(f"[DEBUG] Successfully wrote {length} bytes using ctypes buffer")
except Exception as e2:
print(f"[DEBUG] Also failed with ctypes: {e2}")
raise
return ptr, length
def _read_memory(self, ptr: int, length: int) -> bytes:
"""Read bytes from WASM memory"""
mem_ptr = self.memory.data_ptr(self.store)
print(f"[DEBUG] Reading {length} bytes from ptr={ptr}, memory_ptr type={type(mem_ptr)}")
try:
# Try direct indexing of ctypes pointer
result = []
for i in range(length):
result.append(mem_ptr[ptr + i])
return bytes(result)
except TypeError as e:
print(f"[DEBUG] Error reading with direct indexing: {e}")
# Try converting to address and using ctypes
try:
addr = ctypes.cast(mem_ptr, ctypes.c_void_p).value
print(f"[DEBUG] Memory address: {addr}")
buffer = (ctypes.c_ubyte * length).from_address(addr + ptr)
return bytes(buffer)
except Exception as e2:
print(f"[DEBUG] Also failed with ctypes: {e2}")
raise
def calculate_hash(self, challenge: str, salt: str, difficulty: int, expire_at: int) -> int:
"""Calculate hash using WASM solver"""
print(f"[DEBUG] calculate_hash called with challenge={challenge[:20]}..., salt={salt}, difficulty={difficulty}")
prefix = f"{salt}_{expire_at}_"
# Adjust stack pointer - pass store as first argument
retptr = self.stack_ptr_fn(self.store, -16)
print(f"[DEBUG] Stack pointer adjusted, retptr={retptr}")
# Write to memory
challenge_ptr, challenge_len = self._write_to_memory(challenge)
prefix_ptr, prefix_len = self._write_to_memory(prefix)
print(f"[DEBUG] Wrote challenge at {challenge_ptr}, prefix at {prefix_ptr}")
# Call solve function - pass store as first argument
print(f"[DEBUG] Calling solve function with retptr={retptr}, challenge_ptr={challenge_ptr}, difficulty={difficulty}")
self.solve_fn(self.store, retptr, challenge_ptr, challenge_len, prefix_ptr, prefix_len, float(difficulty))
# Read result from memory
status_bytes = self._read_memory(retptr, 4)
status = struct.unpack('<I', status_bytes)[0]
print(f"[DEBUG] Status: {status}")
if status == 0:
raise Exception("No solution found")
# Read the answer as float64
value_bytes = self._read_memory(retptr + 8, 8)
value = struct.unpack('<d', value_bytes)[0]
print(f"[DEBUG] Value from memory: {value}")
# Convert float to int
answer = int(value)
print(f"[DEBUG] Final answer: {answer}")
# Reset stack pointer - pass store as first argument
self.stack_ptr_fn(self.store, 16)
return answer
def close(self):
"""Close the solver"""
self.store = None
self.instance = None