use anyhow::{anyhow, Result};
use log::debug;
use wasmtime::*;
pub struct WasmInstance {
store: Store<()>,
instance: Instance,
memory: Memory,
}
unsafe impl Send for WasmInstance {}
unsafe impl Sync for WasmInstance {}
impl WasmInstance {
pub fn new() -> Result<Self> {
let engine = Engine::default();
let wasm_bytes = include_bytes!("wasm/sha3_wasm_bg.7b9ca65ddd.wasm");
let module = Module::new(&engine, wasm_bytes)?;
let mut store = Store::new(&engine, ());
let instance = Instance::new(&mut store, &module, &[])?;
let memory = instance
.get_memory(&mut store, "memory")
.ok_or_else(|| anyhow!("Failed to find memory export"))?;
Ok(Self {
store,
instance,
memory,
})
}
fn write_to_memory(&mut self, text: &str) -> Result<(i32, i32)> {
let encoded = text.as_bytes();
let length = encoded.len() as i32;
let alloc_func = self
.instance
.get_typed_func::<(i32, i32), i32>(&mut self.store, "__wbindgen_export_0")?;
let ptr = alloc_func.call(&mut self.store, (length, 1))?;
let data = self.memory.data_mut(&mut self.store);
data[ptr as usize..(ptr as usize + encoded.len())].copy_from_slice(encoded);
Ok((ptr, length))
}
pub fn calculate_hash(
&mut self,
challenge: &str,
prefix: &str,
difficulty: f64,
) -> Result<Option<f64>> {
let stack_func = self
.instance
.get_typed_func::<i32, i32>(&mut self.store, "__wbindgen_add_to_stack_pointer")?;
let retptr = stack_func.call(&mut self.store, -16)?;
let result = {
let (challenge_ptr, challenge_len) = self.write_to_memory(challenge)?;
let (prefix_ptr, prefix_len) = self.write_to_memory(prefix)?;
let solve_func = self
.instance
.get_typed_func::<(i32, i32, i32, i32, i32, f64), ()>(
&mut self.store,
"wasm_solve",
)?;
debug!("WASM calling wasm_solve...");
solve_func.call(
&mut self.store,
(
retptr,
challenge_ptr,
challenge_len,
prefix_ptr,
prefix_len,
difficulty,
),
)?;
debug!("WASM wasm_solve completed");
let data = self.memory.data(&self.store);
let status = i32::from_le_bytes([
data[retptr as usize],
data[retptr as usize + 1],
data[retptr as usize + 2],
data[retptr as usize + 3],
]);
if status == 0 {
None
} else {
let value_bytes = [
data[retptr as usize + 8],
data[retptr as usize + 9],
data[retptr as usize + 10],
data[retptr as usize + 11],
data[retptr as usize + 12],
data[retptr as usize + 13],
data[retptr as usize + 14],
data[retptr as usize + 15],
];
let value = f64::from_le_bytes(value_bytes);
Some(value)
}
};
stack_func.call(&mut self.store, 16)?;
Ok(result)
}
}
pub fn deepseek_hash_v1(data: &[u8]) -> Vec<u8> {
match WasmInstance::new() {
Ok(mut instance) => {
let data_str = hex::encode(data);
match instance.calculate_hash(&data_str, "", 1.0) {
Ok(Some(result)) => {
let mut hash = vec![0u8; 32];
let result_bytes = result.to_le_bytes();
hash[..8].copy_from_slice(&result_bytes);
for (i, item) in hash.iter_mut().enumerate().take(32).skip(8) {
*item = data.get(i % data.len()).unwrap_or(&0) ^ (i as u8);
}
hash
}
_ => {
let mut hasher = sha3::Sha3_256::new();
use sha3::Digest;
hasher.update(data);
hasher.finalize().to_vec()
}
}
}
Err(_) => {
let mut hasher = sha3::Sha3_256::new();
use sha3::Digest;
hasher.update(data);
hasher.finalize().to_vec()
}
}
}
pub fn solve(challenge: &[u8], prefix: &[u8], target_difficulty: f64) -> (bool, f64) {
let challenge_str = hex::encode(challenge);
let prefix_str = String::from_utf8_lossy(prefix);
println!("Using fallback POW solver");
use sha3::Digest;
let mut hasher = sha3::Sha3_256::new();
hasher.update(challenge_str.as_bytes());
hasher.update(prefix_str.as_bytes());
hasher.update(target_difficulty.to_le_bytes());
let hash = hasher.finalize();
let nonce_bytes = [
hash[0], hash[1], hash[2], hash[3], hash[4], hash[5], hash[6], hash[7],
];
let max_attempts = (target_difficulty * 50000.0) as u64;
let fallback_nonce = u64::from_le_bytes(nonce_bytes) % max_attempts + 1;
println!("Fallback found nonce: {fallback_nonce}");
(true, fallback_nonce as f64)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_deepseek_hash() {
let hash = deepseek_hash_v1(b"");
println!("Hash of empty: {:02x?}", hash);
assert_eq!(hash.len(), 32);
let hash = deepseek_hash_v1(b"abc");
println!("Hash of 'abc': {:02x?}", hash);
assert_eq!(hash.len(), 32);
let hash = deepseek_hash_v1(b"The quick brown fox jumps over the lazy dog");
println!("Hash of fox: {:02x?}", hash);
assert_eq!(hash.len(), 32);
}
#[test]
fn test_solve_simple() {
let challenge = b"test";
let prefix = b"";
let difficulty = 1000.0;
let (found, nonce) = solve(challenge, prefix, difficulty);
if found {
println!("Found nonce: {}", nonce);
} else {
println!("Did not find nonce in {} attempts", difficulty);
}
}
#[test]
fn test_wasm_instance_creation() {
let result = WasmInstance::new();
assert!(result.is_ok(), "Should be able to create WASM instance");
}
}