Proof of Hardware is a proposed verification layer for mining clients. The objective is to reduce practical bypass options for disallowed hardware classes by combining environment checks, software and driver checks, hardware signal checks, and runtime integrity checks.
This document describes the model and current prototype direction. It does not claim full tamper proof behavior.
| Stage | Check class | Signals | Expected behavior on failure |
|---|---|---|---|
| 1 | Environment gate | Supported OS profile and policy baseline. | Startup blocked before hash loop. |
| 2 | Software and driver scan | Known vendor software, drivers, logs, process traces. | Session rejected and mining not started. |
| 3 | Hardware signal scan | Kernel modules, PCI or USB traces, system inventory anomalies. | Execution stopped and result path invalidated. |
| 4 | Runtime integrity binding | Module hash plus dynamic values (nonce and block context). | Share or block output rejected. |
use sha3::{Sha3_256, Digest};
use libloading::{Library, Symbol};
use std::fs::File;
use std::io::{self, Read};
use std::ptr;
fn load_file(file_path: &str) -> io::Result<Vec<u8>> {
// Load the DLL file into memory (RAM)
let mut file = File::open(file_path)?;
let mut data = Vec::new();
// Read the content of the file
file.read_to_end(&mut data)?;
Ok(data)
}
// A function that is dynamically loaded from the DLL
type GetDynamicValue = unsafe fn() -> String;
fn load_dynamic_value_from_dll(dll_data: &[u8]) -> Result<String, String> {
// Create a temporary library in memory
let library = Library::new(dll_data).map_err(|e| e.to_string())?;
// Dynamically load a function
unsafe {
let func: Symbol<GetDynamicValue> = library.get(b"get_dynamic_value").map_err(|e| e.to_string())?;
// Call the dynamic value from the DLL
let value = func();
Ok(value)
}
}
// SHA3-256 verification of the DLL and the dynamic value
fn verify_dll_with_sha3(dll_data: &[u8], dynamic_value: &str) -> bool {
let mut data_to_verify = dll_data.to_vec();
data_to_verify.extend_from_slice(dynamic_value.as_bytes());
// Calculate the SHA3-256 hash of the entire content
let mut hasher = Sha3_256::new();
hasher.update(data_to_verify);
let sha3_hash = hasher.finalize();
// Convert the hash to a hex string
let sha3_hash_hex = format!("{:x}", sha3_hash);
// Compare the calculated hash with the expected
println!("Calculated SHA3 hash: {}", sha3_hash_hex);
// For example:
// let expected_hash = fetch_expected_hash_from_blockchain();
// In this case simulate the comparison:
let expected_hash = "expected_dynamic_hash_from_blockchain".to_string();
if sha3_hash_hex == expected_hash {
println!("Verification successful!");
true
} else {
println!("Verification failed!");
false
}
}
fn main() {
let dll_path = "simple-fpga-asic-detect.dll";
// Load the DLL data
match load_file(dll_path) {
Ok(dll_data) => {
// Load the dynamic value from the DLL
match load_dynamic_value_from_dll(&dll_data) {
Ok(dynamic_value) => {
// Perform the SHA3 verification with the DLL and the dynamic value
verify_dll_with_sha3(&dll_data, &dynamic_value);
}
Err(e) => {
println!("Error retrieving dynamic value from the DLL: {}", e);
}
}
}
Err(e) => {
println!("Error loading the DLL file: {}", e);
}
}
}
// The detection of logs, kernel processes, and drivers can obviously be obfuscated or hidden. This creates significant work for manufacturers to detect and prevent it, or to find a bypass method.
// However, hardware checks that need to be added are not as easily obfuscated or bypassed.
// Possible methods for hardware detection:
// Physical device detection: Directly identifying FPGA or ASIC hardware within the system.
// Real-time device communication: Monitoring actual communication and interaction between hardware components in the system.
// Hardware identification via direct access: Identifying hardware components through direct access to system resources (e.g., through the PCI bus or low-level APIs).
// Todo:
// - Add Windows compatibly
// - Add Hardware Detection
// - Integrate the Hash Function for the POW
// - Integrate the dyn Data for non-manipulation final hash of the file
// - Add Runtime Decryption
// - Add hash-based integrity check
// - Operating system test (win + linux + hive ). No Linux embed systems (Bitstreams)
extern "C" {
bool CheckFPGAOrASIC() {
bool hardwareDetected = false;
std::string command;
FILE *fp = nullptr;
// FPGA drivers are loaded as kernel modules
command = "lsmod | grep -i \\"xilinx\\" || lsmod | grep -i \\"altera\\" || lsmod | grep -i \\"cyclone\\" || lsmod | grep -i \\"arria\\" || lsmod | grep -i \\"stratix\\" || lsmod | grep -i \\"lattice\\" || lsmod | grep -i \\"microsemi\\" || lsmod | grep -i \\"achronix\\" || lsmod | grep -i \\"quicklogic\\"";
fp = popen(command.c_str(), "r");
if (fp == nullptr) {
std::cerr << "Error: Cannot retrieve driver information (lsmod)." << std::endl;
return false;
}
char path[1035];
while (fgets(path, sizeof(path), fp) != nullptr) {
std::cout << "FPGA driver found: " << path;
hardwareDetected = true;
}
fclose(fp);
// FPGA devices via PCI
if (!hardwareDetected) {
command = "lspci | grep -i \\"xilinx\\" || lspci | grep -i \\"altera\\" || lspci | grep -i \\"cyclone\\" || lspci | grep -i \\"arria\\" || lspci | grep -i \\"stratix\\" || lspci | grep -i \\"intel\\" || lspci | grep -i \\"lattice\\" || lspci | grep -i \\"microsemi\\" || lspci | grep -i \\"achronix\\" || lspci | grep -i \\"quicklogic\\"";
fp = popen(command.c_str(), "r");
if (fp == nullptr) {
std::cerr << "Error: Cannot retrieve PCI device list (lspci)." << std::endl;
return false;
}
while (fgets(path, sizeof(path), fp) != nullptr) {
std::cout << "FPGA device found via PCI: " << path;
hardwareDetected = true;
}
fclose(fp);
}
// dmesg logs for FPGA/ASIC related messages
if (!hardwareDetected) {
command = "dmesg | grep -i \\"xilinx\\" || dmesg | grep -i \\"altera\\" || dmesg | grep -i \\"cyclone\\" || dmesg | grep -i \\"arria\\" || dmesg | grep -i \\"stratix\\" || dmesg | grep -i \\"lattice\\" || dmesg | grep -i \\"microsemi\\" || dmesg | grep -i \\"achronix\\" || dmesg | grep -i \\"quicklogic\\" || dmesg | grep -i \\"asic\\" || dmesg | grep -i \\"bitmain\\" || dmesg | grep -i \\"canaan\\" || dmesg | grep -i \\"innosilicon\\" || dmesg | grep -i \\"ebang\\" || dmesg | grep -i \\"microbt\\"";
fp = popen(command.c_str(), "r");
if (fp == nullptr) {
std::cerr << "Error: Cannot retrieve dmesg logs." << std::endl;
return false;
}
while (fgets(path, sizeof(path), fp) != nullptr) {
std::cout << "FPGA or ASIC detected in dmesg logs: " << path;
hardwareDetected = true;
}
fclose(fp);
}
// FPGA/ASIC devices with lshw
if (!hardwareDetected) {
command = "lshw -class system | grep -i \\"fpga\\" || lshw -class system | grep -i \\"asic\\" || lshw -class system | grep -i \\"xilinx\\" || lshw -class system | grep -i \\"altera\\" || lshw -class system | grep -i \\"cyclone\\" || lshw -class system | grep -i \\"arria\\" || lshw -class system | grep -i \\"stratix\\" || lshw -class system | grep -i \\"lattice\\" || lshw -class system | grep -i \\"microsemi\\" || lshw -class system | grep -i \\"achronix\\" || lshw -class system | grep -i \\"quicklogic\\"";
fp = popen(command.c_str(), "r");
if (fp == nullptr) {
std::cerr << "Error: Cannot retrieve hardware information (lshw)." << std::endl;
return false;
}
while (fgets(path, sizeof(path), fp) != nullptr) {
std::cout << "FPGA or ASIC device detected with lshw: " << path;
hardwareDetected = true;
}
fclose(fp);
}
// FPGA-related software or processes
if (!hardwareDetected) {
command = "ps aux | grep -i \\"xilinx\\" || ps aux | grep -i \\"altera\\" || ps aux | grep -i \\"cyclone\\" || ps aux | grep -i \\"arria\\" || ps aux | grep -i \\"stratix\\" || ps aux | grep -i \\"lattice\\" || ps aux | grep -i \\"microsemi\\" || ps aux | grep -i \\"achronix\\" || ps aux | grep -i \\"quicklogic\\"";
fp = popen(command.c_str(), "r");
if (fp == nullptr) {
std::cerr << "Error: Cannot retrieve process list (ps)." << std::endl;
return false;
}
while (fgets(path, sizeof(path), fp) != nullptr) {
std::cout << "FPGA-related processes detected: " << path;
hardwareDetected = true;
}
fclose(fp);
}
// ASIC-related software or processes
if (!hardwareDetected) {
command = "ps aux | grep -i \\"bitmain\\" || ps aux | grep -i \\"canaan\\" || ps aux | grep -i \\"innosilicon\\" || ps aux | grep -i \\"ebang\\" || ps aux | grep -i \\"microbt\\"";
fp = popen(command.c_str(), "r");
if (fp == nullptr) {
std::cerr << "Error: Cannot retrieve ASIC-related processes." << std::endl;
return false;
}
while (fgets(path, sizeof(path), fp) != nullptr) {
std::cout << "ASIC-related processes detected: " << path;
hardwareDetected = true;
}
fclose(fp);
}
if (hardwareDetected) {
std::cout << "FPGA or ASIC detected. Mining is not allowed." << std::endl;
return false;
}
std::cout << "No FPGA or ASIC detected. Proceeding with mining..." << std::endl;
return true;
}
}
Note: snippets are prototype examples for research discussion and are not final production code.