Skip to content

Conversation

@haqatak
Copy link

@haqatak haqatak commented Aug 1, 2025

Summary by CodeRabbit

  • New Features

    • Added support for Apple's Metal GPU backend, enabling key search operations on Metal-compatible devices.
    • Introduced a new device type "Metal" selectable alongside existing CUDA and OpenCL options.
    • Provided a Metal-based implementation for GPU-accelerated key generation, including foundational elliptic curve arithmetic for secp256k1.
    • Added new build options and binaries for Metal support.
  • Chores

    • Updated build scripts and Makefiles to support Metal backend compilation and integration.

This commit adds an experimental backend for Apple Silicon using the PyTorch MPS (Metal Performance Shaders) backend. This is intended to allow BitCrack to run on Apple M-series GPUs.

The new `MpsKeySearchDevice` class implements the `KeySearchDevice` interface and uses libtorch for computation. The build system has been updated to support building with libtorch when the `BUILD_MPS=1` flag is provided.

Note: I haven't compiled or tested the code because the `libtorch` dependency was not available in my development environment. You will need to have libtorch installed and may need to adjust the `LIBTORCH_HOME` path in the `Makefile` to match your installation.
This commit fixes a linker error on macOS where the 'crypto' library could not be found. This was because the linker was not looking in the standard Homebrew installation path for OpenSSL.

The Makefile is updated to include the Homebrew OpenSSL include and library paths when compiling on Darwin (macOS). This should allow the project to be built on macOS without manual configuration of OpenSSL paths, assuming OpenSSL was installed with Homebrew.
This commit fixes a linker error on Apple Silicon Macs where the 'crypto' library could not be found. This was because the linker was not looking in the correct Homebrew installation path for OpenSSL on Apple Silicon machines.

The Makefile is updated to include the `/opt/homebrew/opt/openssl` include and library paths when compiling on Darwin (macOS). This should allow the project to be built on Apple Silicon Macs without manual configuration of OpenSSL paths, assuming OpenSSL was installed with Homebrew.
This commit fixes a linker error when building the 'addrgen' executable on macOS. The `LDFLAGS` variable, which contains the path to the OpenSSL library, was not being passed to the linker.

This resulted in a "library not found" error for the 'crypto' library. The `AddrGen/Makefile` has been updated to include `LDFLAGS` in the linker command.
This commit fixes a build failure on macOS when using a libtorch installation from a miniconda environment. The `LIBTORCH_HOME` path in the `Makefile` was hardcoded to `/usr/local/libtorch`, which is not correct for this setup.

The `Makefile` has been updated to point to the user-provided path for the miniconda-based libtorch installation. This should allow the project to be built successfully with the MPS backend.
This commit fixes a build failure when compiling with PyTorch. The version of PyTorch being used requires a C++17 compatible compiler, but the project was being built with C++11.

The `Makefile` has been updated to use the `-std=c++17` flag, which should resolve the compilation errors related to C++17 features.
This commit fixes a build failure where the `MpsKeySearchDevice.h` header could not be found when compiling `main.cpp`.

The `MpsKeySearchDevice` directory was not included in the `DIRS` variable in the main `Makefile`, which meant that the compiler was not looking in the correct directory for the header file. This has been corrected.
This commit fixes a linker error when building with the MPS backend on macOS. The torch libraries were not being linked in the correct order, which resulted in "undefined symbol" errors for torch functions.

The `KeyFinder/Makefile` has been updated to explicitly link the torch libraries at the end of the linker command, which resolves the issue.
This commit fixes a linker error when building with the MPS backend on macOS. The torch libraries were being included twice in the linker command, which caused the linker to fail with "undefined symbol" errors.

The `KeyFinder/Makefile` has been updated to remove the duplicate `-ltorch` and `-lc10` flags. The `LIBS` variable, which is passed from the main `Makefile`, already contains these flags, so they are not needed here.
@coderabbitai
Copy link

coderabbitai bot commented Aug 1, 2025

Walkthrough

This change introduces a new Metal-based GPU backend for key searching, adding support for Apple's Metal API alongside existing CUDA and OpenCL backends. It includes new source files, build system updates, device enumeration and selection logic, and a Metal kernel for secp256k1 elliptic curve operations. Build scripts and device type enumerations are updated accordingly.

Changes

Cohort / File(s) Change Summary
Build System: Top-Level and Subproject Makefiles
Makefile, AddrGen/Makefile, KeyFinder/Makefile, MetalKeySearchDevice/Makefile, Makefile.metal
Added BUILD_METAL build flag, Metal backend build rules, Metal-specific compiler/linker settings, and clean targets. Integrated MetalKeySearchDevice as a build target and dependency. Added new Makefile for Metal backend build on macOS.
Device Manager and Device Type Enumeration
KeyFinder/DeviceManager.cpp, KeyFinder/DeviceManager.h
Added Metal device detection and enumeration under BUILD_METAL. Extended DeviceType enum to include Metal.
KeyFinder Main Application
KeyFinder/main.cpp
Added support for instantiating MetalKeySearchDevice when the Metal device type is selected. Conditional includes and logic under BUILD_METAL.
MetalKeySearchDevice Implementation
MetalKeySearchDevice/MetalKeySearchDevice.cpp, MetalKeySearchDevice/MetalKeySearchDevice.h
Introduced new MetalKeySearchDevice class implementing the key search device interface using Apple's Metal API. Handles device initialization, kernel dispatch, and key stepping.
Metal Kernel (Shader) Code
MetalKeySearchDevice/keysearch.metal
Added Metal shader implementing secp256k1 arithmetic, elliptic curve operations, and a kernel for public key generation from private keys.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant MainApp
    participant DeviceManager
    participant MetalKeySearchDevice
    participant MetalAPI

    User->>MainApp: Start key search (with Metal enabled)
    MainApp->>DeviceManager: getDevices()
    DeviceManager->>MetalAPI: Query system Metal devices
    MetalAPI-->>DeviceManager: Return Metal device info
    DeviceManager-->>MainApp: List devices (including Metal)
    MainApp->>MetalKeySearchDevice: Instantiate device
    MetalKeySearchDevice->>MetalAPI: Initialize Metal device, compile kernel
    MainApp->>MetalKeySearchDevice: init(start, compression, stride)
    loop For each step
        MainApp->>MetalKeySearchDevice: doStep()
        MetalKeySearchDevice->>MetalAPI: Dispatch kernel (generate_public_key)
        MetalAPI-->>MetalKeySearchDevice: Kernel execution complete
        MetalKeySearchDevice-->>MainApp: (Results pending: TODO)
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

A shiny new path for the keys to be cracked,
Metal bunnies hop where CUDA once tracked.
With kernels that shimmer and shaders that gleam,
The orchard now grows with a silvery beam.
Makefiles are polished, devices now three—
More ways for a rabbit to search with glee!
🐇✨

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7f0db08 and 74b9d33.

📒 Files selected for processing (1)
  • Makefile.metal (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • Makefile.metal
✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (5)
KeyFinder/DeviceManager.cpp (1)

64-76: Consider improving error handling for MPS device initialization.

The MPS device detection logic follows the existing pattern well, but there are a few considerations:

  1. Setting physicalId, memory, and computeUnits to 0 might be misleading for users who expect meaningful device information
  2. No exception handling around torch::mps::is_available() - if this throws, it could crash the application

Consider this improvement:

 #ifdef BUILD_MPS
-    if(torch::mps::is_available()) {
+    try {
+        if(torch::mps::is_available()) {
+            DeviceManager::DeviceInfo device;
+            device.name = "Apple MPS";
+            device.type = DeviceType::MPS;
+            device.id = deviceId;
+            device.physicalId = 0;  // TODO: Get actual MPS device info if available
+            device.memory = 0;      // TODO: Query MPS memory if possible
+            device.computeUnits = 0; // TODO: Query MPS compute units if possible
+            devices.push_back(device);
+            deviceId++;
+        }
+    } catch(const std::exception& ex) {
+        // Log warning but don't fail - MPS is optional
+        // Consider logging: "Warning: MPS device detection failed: " + ex.what()
+    }
MpsKeySearchDevice/MpsKeySearchDevice.cpp (4)

4-10: Good device validation but consider more robust error handling.

The constructor properly checks MPS availability before proceeding, which prevents runtime failures. However, there are a few suggestions:

  1. The exception type KeySearchException should be properly included/declared
  2. Consider logging device creation at a different level than stdout
 MpsKeySearchDevice::MpsKeySearchDevice(int deviceId, uint64_t keysPerStep) : _device(torch::kMPS) {
     if (!torch::mps::is_available()) {
         throw KeySearchException("MPS device not available");
     }
     this->_keysPerStep = keysPerStep;
-    std::cout << "MpsKeySearchDevice created" << std::endl;
+    // Consider using a logging framework instead of direct stdout
 }

12-14: Consider removing debug output from production code.

The destructor logging to stdout may not be appropriate for production usage.

 MpsKeySearchDevice::~MpsKeySearchDevice() {
-    std::cout << "MpsKeySearchDevice destroyed" << std::endl;
+    // Consider using a logging framework or removing debug output
 }

16-21: Initialization method is correct but has debug output.

The parameter assignment logic is sound, but consider removing or replacing the debug output.

 void MpsKeySearchDevice::init(const secp256k1::uint256 &start, int compression, const secp256k1::uint256 &stride) {
     this->_startKey = start;
     this->_compression = compression;
     this->_stride = stride;
-    std::cout << "MpsKeySearchDevice::init" << std::endl;
 }

46-50: Consider implementing actual memory information.

While returning zeros is acceptable for a stub implementation, providing actual MPS device memory information would be more useful for users.

Consider querying PyTorch for MPS memory information:

 void MpsKeySearchDevice::getMemoryInfo(uint64_t &freeMem, uint64_t &totalMem) {
-    // Not implemented for MPS
-    freeMem = 0;
-    totalMem = 0;
+    // TODO: Query actual MPS memory if PyTorch provides API
+    // For now, return reasonable defaults or query system memory
+    freeMem = 0;
+    totalMem = 0;
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1530806 and c11f815.

📒 Files selected for processing (9)
  • AddrGen/Makefile (1 hunks)
  • KeyFinder/DeviceManager.cpp (2 hunks)
  • KeyFinder/DeviceManager.h (1 hunks)
  • KeyFinder/Makefile (1 hunks)
  • KeyFinder/main.cpp (2 hunks)
  • Makefile (6 hunks)
  • MpsKeySearchDevice/Makefile (1 hunks)
  • MpsKeySearchDevice/MpsKeySearchDevice.cpp (1 hunks)
  • MpsKeySearchDevice/MpsKeySearchDevice.h (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
MpsKeySearchDevice/MpsKeySearchDevice.cpp (2)
MpsKeySearchDevice/MpsKeySearchDevice.h (1)
  • MpsKeySearchDevice (7-28)
KeyFinderLib/KeySearchDevice.h (1)
  • KeySearchException (10-25)
🪛 checkmake (0.2.2)
MpsKeySearchDevice/Makefile

[warning] 1-1: Missing required phony target "all"

(minphony)


[warning] 1-1: Missing required phony target "clean"

(minphony)


[warning] 1-1: Missing required phony target "test"

(minphony)

🔇 Additional comments (21)
AddrGen/Makefile (1)

4-4: LGTM! Standard build system improvement.

Adding ${LDFLAGS} to the build command is a good practice that provides flexibility for additional linker flags, which is essential for the MPS backend integration.

KeyFinder/DeviceManager.h (1)

25-26: LGTM! Clean extension of device type system.

The addition of the MPS device type follows the existing enum pattern and integrates well with the existing CUDA and OpenCL types.

KeyFinder/Makefile (3)

10-10: LGTM! Consistent with build system improvements.

Adding ${LDFLAGS} to the OpenCL build command maintains consistency with the broader build system updates.


14-18: Well-structured MPS build target.

The new MPS build target follows the established pattern used for CUDA and OpenCL builds, with proper conditional compilation and appropriate library linking.


23-23: Clean target properly updated.

The addition of mpsKeyFinder.bin to the clean target ensures proper cleanup of MPS-related build artifacts.

KeyFinder/main.cpp (2)

23-25: Proper conditional compilation for MPS support.

The conditional include for MpsKeySearchDevice.h follows the established pattern used for CUDA and OpenCL device headers.


258-262: Confirmed MpsKeySearchDevice constructor usage is correct

The constructor in MpsKeySearchDevice/MpsKeySearchDevice.h

MpsKeySearchDevice(int deviceId, uint64_t keysPerStep);

matches the call in KeyFinder/main.cpp (line 260):

return new MpsKeySearchDevice(device.id, pointsPerThread);

No changes required.

KeyFinder/DeviceManager.cpp (1)

11-13: LGTM! Consistent with existing conditional compilation pattern.

The conditional inclusion of <torch/torch.h> follows the same pattern as CUDA and OpenCL includes, maintaining consistency in the codebase structure.

MpsKeySearchDevice/MpsKeySearchDevice.h (4)

1-3: LGTM! Proper header guard naming convention.

The header guard follows a clear naming convention with underscores and matches the filename structure.


4-6: LGTM! Clean dependency management.

The includes are minimal and appropriate - inheriting from the base class and including the required PyTorch headers.


7-15: Well-designed class structure with appropriate member variables.

The private members effectively encapsulate the MPS device state:

  • PyTorch device handle
  • Key management variables (_startKey, _stride)
  • Search configuration (_compression, _targets, _keysPerStep)

The design follows good encapsulation principles.


16-28: Complete and consistent public interface.

The public method declarations properly override all virtual methods from the base KeySearchDevice class, ensuring full interface compliance. The method signatures match the expected pattern for device implementations.

MpsKeySearchDevice/MpsKeySearchDevice.cpp (3)

29-31: LGTM! Proper target conversion.

The conversion from std::set to std::vector is handled correctly using the assign method.


38-44: LGTM! Simple accessor methods work correctly.

Both keysPerStep() and getDeviceName() provide appropriate return values for their respective purposes.


52-54: LGTM! Correct key state access.

The method correctly returns the current key state for external monitoring.

Makefile (6)

3-3: LGTM! MpsKeySearchDevice properly added to build directories.

The addition of MpsKeySearchDevice to the DIRS variable ensures it gets included in the build process consistently with other components.


13-15: Good upgrade to C++17 and addition of LDFLAGS.

The upgrade from C++11 to C++17 is necessary for modern PyTorch compatibility, and the new LDFLAGS variable provides better flexibility for platform-specific linking.


16-35: Comprehensive OS-specific configuration, but hardcoded paths need attention.

The OS detection and platform-specific settings are well-structured. However, there are some concerns:

The hardcoded OpenSSL path /opt/homebrew/opt/openssl assumes Homebrew installation on macOS. This may not work for all users.

Consider making this configurable:

 	ifeq ($(UNAME_S),Darwin)
 		# macOS-specific settings
 		CXX=clang++
 		# Use Apple's OpenCL framework
-		LDFLAGS+=-framework OpenCL -L/opt/homebrew/opt/openssl/lib
-		CXXFLAGS+=-I/opt/homebrew/opt/openssl/include
+		LDFLAGS+=-framework OpenCL
+		# Try multiple common OpenSSL locations
+		ifneq ($(wildcard /opt/homebrew/opt/openssl),)
+			LDFLAGS+=-L/opt/homebrew/opt/openssl/lib
+			CXXFLAGS+=-I/opt/homebrew/opt/openssl/include
+		else ifneq ($(wildcard /usr/local/opt/openssl),)
+			LDFLAGS+=-L/usr/local/opt/openssl/lib
+			CXXFLAGS+=-I/usr/local/opt/openssl/include
+		endif

86-90: LGTM! Proper conditional MPS build configuration.

The conditional MPS build setup correctly adds the necessary compiler flags and library dependencies when BUILD_MPS=1.


101-102: LGTM! Consistent build target pattern.

The new MPS build target follows the same dependency pattern as other device targets, ensuring proper build ordering.


129-131: LGTM! Proper integration with existing dependency system.

The conditional addition of MPS dependencies maintains consistency with the existing CUDA and OpenCL patterns.

Comment on lines 23 to 27
void MpsKeySearchDevice::doStep() {
// This is where the magic happens
// For now, just advance the key
_startKey = _startKey + _stride;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Critical issue: Missing actual MPS computation implementation.

The doStep() method is the core of the key search functionality, but it only advances the key without performing any actual cryptographic operations using MPS. This renders the device non-functional for its intended purpose.

The current implementation only advances the key but doesn't perform the actual elliptic curve operations or address generation that should utilize MPS. You need to implement:

  1. EC point multiplication using MPS/PyTorch tensors
  2. Address generation from public keys
  3. Target matching logic
  4. Result collection

This is a placeholder that needs substantial implementation work.

🤖 Prompt for AI Agents
In MpsKeySearchDevice/MpsKeySearchDevice.cpp around lines 23 to 27, the doStep()
method currently only increments the key without performing any cryptographic
operations. To fix this, implement the core MPS computation by performing
elliptic curve point multiplication using MPS or PyTorch tensors, generate
addresses from the resulting public keys, apply the target matching logic to
check for desired keys, and collect any matching results. Replace the
placeholder increment with this full cryptographic processing workflow.

Comment on lines 33 to 36
size_t MpsKeySearchDevice::getResults(std::vector<KeySearchResult> &results) {
// Not implemented yet
return 0;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Critical issue: Results method is unimplemented.

The getResults() method always returns 0, meaning no search results will ever be reported, even if matches are found.

This method needs to be implemented to return actual search results. The current stub implementation means the device will never report finding target addresses, making it non-functional.

🤖 Prompt for AI Agents
In MpsKeySearchDevice/MpsKeySearchDevice.cpp around lines 33 to 36, the
getResults() method is currently a stub that always returns 0, so it does not
return any actual search results. Implement this method to populate the results
vector with the found KeySearchResult objects and return the count of these
results to correctly report matches found by the device.

This commit refactors the build process for the MPS backend to address a persistent linker error on macOS. Instead of modifying the global `LIBS` variable, the torch library path and libraries are now explicitly added to the linker command in the `KeyFinder/Makefile`.

This makes the build process for the `mpsKeyFinder` executable more self-contained and should resolve the "undefined symbol" errors by ensuring the correct library link order.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
Makefile (1)

70-73: Hard-coded LIBTORCH_HOME path still present
Same portability issue previously reported: a user-specific absolute path will break every other workstation / CI image.

See prior review; please make this configurable or auto-detected.

🧹 Nitpick comments (1)
Makefile (1)

16-35: macOS section: duplicated -lstdc++, absent RTTI flags, and OpenSSL path hard-wired

  1. LIBS+=-lstdc++ while clang++ already links libc++ by default; this may pull in two C++ std-libs.
  2. If OpenSSL is installed elsewhere (Intel Homebrew prefix, MacPorts, system SDK) the hard path fails.
  3. Consider -stdlib=libc++ to avoid mis-linking with libstdc++.

Worth revisiting before wider distribution.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c11f815 and 24045c8.

📒 Files selected for processing (2)
  • KeyFinder/Makefile (1 hunks)
  • Makefile (6 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • KeyFinder/Makefile

Makefile Outdated
Comment on lines 86 to 90
ifeq ($(BUILD_MPS),1)
TARGETS:=${TARGETS} dir_mpsKeySearchDevice
CXXFLAGS:=${CXXFLAGS} -I${LIBTORCH_INCLUDE} -I${LIBTORCH_INCLUDE}/torch/csrc/api/include
endif

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

MPS build missing Torch libraries in link flags

CXXFLAGS adds the Torch include dirs, but neither LIBS nor LDFLAGS receive ${LIBTORCH_LIB} or the required -ltorch -ltorch_cpu -lc10 set. Any target that links against MpsKeySearchDevice will fail with “undefined symbol” errors.

ifeq ($(BUILD_MPS),1)
   TARGETS:=${TARGETS} dir_mpsKeySearchDevice
   CXXFLAGS:=${CXXFLAGS} -I${LIBTORCH_INCLUDE} -I${LIBTORCH_INCLUDE}/torch/csrc/api/include
+  LIBS+=-L${LIBTORCH_LIB} -ltorch -ltorch_cpu -lc10
+  LDFLAGS+=-L${LIBTORCH_LIB} -ltorch -ltorch_cpu -lc10
 endif

Make sure ${LIBTORCH_LIB} is exported so sub-Makefiles inherit it.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
ifeq ($(BUILD_MPS),1)
TARGETS:=${TARGETS} dir_mpsKeySearchDevice
CXXFLAGS:=${CXXFLAGS} -I${LIBTORCH_INCLUDE} -I${LIBTORCH_INCLUDE}/torch/csrc/api/include
endif
ifeq ($(BUILD_MPS),1)
TARGETS:=${TARGETS} dir_mpsKeySearchDevice
CXXFLAGS:=${CXXFLAGS} -I${LIBTORCH_INCLUDE} -I${LIBTORCH_INCLUDE}/torch/csrc/api/include
LIBS+=-L${LIBTORCH_LIB} -ltorch -ltorch_cpu -lc10
LDFLAGS+=-L${LIBTORCH_LIB} -ltorch -ltorch_cpu -lc10
endif
🤖 Prompt for AI Agents
In the Makefile around lines 86 to 90, the MPS build section adds Torch include
directories to CXXFLAGS but does not add the necessary Torch libraries to LIBS
or LDFLAGS, causing linking errors. To fix this, append ${LIBTORCH_LIB} and the
required libraries (-ltorch -ltorch_cpu -lc10) to the LIBS or LDFLAGS variables
within the ifeq block. Also, ensure that ${LIBTORCH_LIB} is exported so that
sub-Makefiles inherit it properly.

This commit addresses several issues identified in the code review for the new MPS backend. The following changes have been made:

- **Makefile:**
  - The `LIBTORCH_HOME` path is now configurable and defaults to the user's miniconda environment.
  - The C++ standard for `nvcc` has been updated to C++17 to match the rest of the project.
  - The torch libraries are now correctly added to the `LIBS` variable for the MPS build.

- **DeviceManager:**
  - Added a `try...catch` block around the `torch::mps::is_available()` call to prevent crashes if torch throws an exception.
  - Added `TODO` comments to indicate that the MPS device information is not yet fully implemented.

- **MpsKeySearchDevice:**
  - Replaced `std::cout` with the existing `Logger` for consistency.
  - Added `TODO` comments to mark the unimplemented `doStep` and `getResults` methods.
  - Added `.PHONY` targets to the `MpsKeySearchDevice/Makefile` for `all` and `clean`.

These changes should improve the robustness and portability of the build process for the MPS backend.
This commit addresses several issues identified in the code review for the new MPS backend. The following changes have been made:

- **Makefile:**
  - The `LIBTORCH_HOME` path is now configurable and defaults to the user's miniconda environment.
  - The C++ standard for `nvcc` has been updated to C++17 to match the rest of the project.
  - The torch libraries are now correctly added to the `LIBS` variable for the MPS build.

- **DeviceManager:**
  - Added a `try...catch` block around the `torch::mps::is_available()` call to prevent crashes if torch throws an exception.
  - Added `TODO` comments to indicate that the MPS device information is not yet fully implemented.

- **MpsKeySearchDevice:**
  - Replaced `std::cout` with the existing `Logger` for consistency.
  - Added `TODO` comments to mark the unimplemented `doStep` and `getResults` methods.
  - Added `.PHONY` targets to the `MpsKeySearchDevice/Makefile` for `all` and `clean`.

These changes should improve the robustness and portability of the build process for the MPS backend.
This commit removes the explicit linking of torch libraries from the `KeyFinder/Makefile`. These libraries are already included in the `LIBS` variable from the main `Makefile`, and the duplication was causing linker errors on macOS.

This change should resolve the "undefined symbol" errors for torch functions by ensuring that the libraries are linked only once and in the correct order.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (2)
MpsKeySearchDevice/MpsKeySearchDevice.cpp (2)

23-30: Critical issue: Missing actual MPS computation implementation.

The doStep() method only advances the key without performing any actual cryptographic operations using MPS. This renders the device non-functional for its intended purpose.


36-41: Critical issue: Results method is unimplemented.

The getResults() method always returns 0, meaning no search results will ever be reported, even if matches are found.

🧹 Nitpick comments (1)
Makefile (1)

71-73: Good: Libtorch path is now configurable via environment variable.

The use of ?= allows overriding via environment variable, addressing the portability issue. Consider adding auto-detection for better user experience:

 # Libtorch variables
 LIBTORCH_HOME?=/Users/haq/miniconda3/lib/python3.12/site-packages/torch
+
+# Auto-detect if not specified and python/torch available
+ifeq ($(LIBTORCH_HOME),/Users/haq/miniconda3/lib/python3.12/site-packages/torch)
+    PYTHON_TORCH_PATH := $(shell python -c "import torch; print(torch.__path__[0])" 2>/dev/null)
+    ifneq ($(PYTHON_TORCH_PATH),)
+        LIBTORCH_HOME := $(PYTHON_TORCH_PATH)
+    endif
+endif
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 24045c8 and 343d969.

📒 Files selected for processing (5)
  • KeyFinder/DeviceManager.cpp (2 hunks)
  • KeyFinder/Makefile (1 hunks)
  • Makefile (6 hunks)
  • MpsKeySearchDevice/Makefile (1 hunks)
  • MpsKeySearchDevice/MpsKeySearchDevice.cpp (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • KeyFinder/DeviceManager.cpp
  • KeyFinder/Makefile
🧰 Additional context used
🧬 Code Graph Analysis (1)
MpsKeySearchDevice/MpsKeySearchDevice.cpp (2)
MpsKeySearchDevice/MpsKeySearchDevice.h (1)
  • MpsKeySearchDevice (7-28)
KeyFinderLib/KeySearchDevice.h (1)
  • KeySearchException (10-25)
🪛 checkmake (0.2.2)
MpsKeySearchDevice/Makefile

[warning] 1-1: Missing required phony target "test"

(minphony)

🔇 Additional comments (3)
MpsKeySearchDevice/Makefile (1)

1-15: Well-structured Makefile with proper phony targets.

The Makefile correctly implements the build process with appropriate .PHONY declarations and follows the project's build patterns.

Makefile (2)

13-41: Good: C++ standard is now consistent across all compilers.

The upgrade to C++17 for both CXX and NVCC resolves the previous standard mismatch issue. The OS-specific settings appropriately handle platform differences.


86-90: Ensure all required LibTorch libraries are linked for MPS

The current LIBS line in your Makefile only links -ltorch and -lc10, but a LibTorch MPS build often ships with additional libraries (for example, torch_cpu for CPU fallback or a backend-specific library). Please verify and update:

  • Inspect your $(LIBTORCH_LIB) directory:
    ls $(LIBTORCH_LIB) | grep -E 'torch|c10'
  • If you see libtorch_cpu.*, add -ltorch_cpu to LIBS.
  • If there’s a backend-specific library (e.g. libc10_mps.*), add -lc10_mps.

This will ensure you won’t encounter missing-symbol errors when running on MPS.

This commit refactors the build process for the MPS backend to further isolate the torch library linking and hopefully resolve the persistent linker errors on macOS.

The torch-related `LIBS` modifications have been removed from the main `Makefile`, and the library path and libraries are now added directly to the `KeyFinder/Makefile`. This makes the `mpsKeyFinder` build command self-contained and should prevent any issues with linker flag ordering.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (2)
Makefile (2)

86-90: Torch libraries still not linked – build will fail (undefined symbol)
Previous review flagged this; the include paths were added but -L${LIBTORCH_LIB} -ltorch -ltorch_cpu -lc10 are still missing.

ifeq ($(BUILD_MPS),1)
     TARGETS:=${TARGETS} dir_mpsKeySearchDevice
     CXXFLAGS:=${CXXFLAGS} -I${LIBTORCH_INCLUDE} -I${LIBTORCH_INCLUDE}/torch/csrc/api/include
+    LIBS+=-L${LIBTORCH_LIB} -ltorch -ltorch_cpu -lc10
+    LDFLAGS+=-L${LIBTORCH_LIB} -ltorch -ltorch_cpu -lc10
 endif

70-73: Default LIBTORCH_HOME still points to a personal path – add auto-detection fallback
?= allows override, but CI & fresh clones will still default to /Users/haq/..., breaking non-HaQ machines. Provide detection:

-LIBTORCH_HOME?=/Users/haq/miniconda3/lib/python3.12/site-packages/torch
+ifndef LIBTORCH_HOME
+  LIBTORCH_HOME:=$(shell python - <<'PY' 2>/dev/null
+import importlib.util, sys
+spec = importlib.util.find_spec("torch")
+print(spec.submodule_search_locations[0] if spec else "", end="")
+PY
+  )
+endif
🧹 Nitpick comments (1)
Makefile (1)

68-69: BUILD_MPS is exported but never initialised – default to 0 to avoid accidental enablement

-export BUILD_MPS
+BUILD_MPS ?= 0
+export BUILD_MPS
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 343d969 and 39468d9.

📒 Files selected for processing (2)
  • KeyFinder/Makefile (1 hunks)
  • Makefile (6 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • KeyFinder/Makefile

Makefile Outdated
Comment on lines 16 to 35
# Check for OS
ifeq ($(OS),Windows_NT)
# Windows-specific settings
else
UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Linux)
# Linux-specific settings
LIBS+=-lstdc++ -lcrypto
endif
ifeq ($(UNAME_S),Darwin)
# macOS-specific settings
CXX=clang++
# Use Apple's OpenCL framework
LDFLAGS+=-framework OpenCL -L/opt/homebrew/opt/openssl/lib
CXXFLAGS+=-I/opt/homebrew/opt/openssl/include
LIBS+=-lstdc++ -lcrypto
# Suppress unused parameter warnings that are common in cross-platform code
CXXFLAGS+=-Wno-unused-parameter
endif
endif
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

macOS section hard-codes OpenSSL include/lib paths
Relying on Homebrew’s default location (/opt/homebrew/…) breaks on Intel Macs and non-Homebrew setups. Prefer pkg-config or an overridable variable, e.g.:

-   LDFLAGS+=-framework OpenCL -L/opt/homebrew/opt/openssl/lib
-   CXXFLAGS+=-I/opt/homebrew/opt/openssl/include
+   OPENSSL_PREFIX ?=$(shell brew --prefix openssl@3 2>/dev/null)
+   ifneq ($(OPENSSL_PREFIX),)
+     LDFLAGS+=-framework OpenCL -L$(OPENSSL_PREFIX)/lib
+     CXXFLAGS+=-I$(OPENSSL_PREFIX)/include
+   else
+     $(warning OpenSSL not found – override OPENSSL_PREFIX)
+   endif
🤖 Prompt for AI Agents
In the Makefile between lines 16 and 35, the macOS section hard-codes OpenSSL
include and library paths to Homebrew's default location, which fails on Intel
Macs or non-Homebrew setups. Replace these hard-coded paths with a call to
pkg-config to dynamically obtain the correct include and library flags for
OpenSSL, or define variables that can be overridden externally to specify these
paths. Update LDFLAGS and CXXFLAGS accordingly to use these dynamic or
variable-based paths instead of fixed ones.

Makefile Outdated
COMPUTE_CAP=86
NVCC=nvcc
NVCCFLAGS=-std=c++11 -gencode=arch=compute_${COMPUTE_CAP},code=sm_${COMPUTE_CAP} -Xptxas="-v" -Xcompiler "${CXXFLAGS}"
NVCCFLAGS=-std=c++17 -gencode=arch=compute_${COMPUTE_CAP},code=sm_${COMPUTE_CAP} -Xptxas="-v" -Xcompiler "${CXXFLAGS}"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

NVCCFLAGS embeds $(CXXFLAGS) inside quoted string – may inject spaces twice
-Xcompiler "${CXXFLAGS}" keeps the quotes, so the resulting command line contains a literal space-separated string inside one argument, not multiple flags. Use unquoted expansion:

- NVCCFLAGS=-std=c++17 -gencode=arch=compute_${COMPUTE_CAP},code=sm_${COMPUTE_CAP} -Xptxas="-v" -Xcompiler "${CXXFLAGS}"
+ NVCCFLAGS=-std=c++17 -gencode=arch=compute_${COMPUTE_CAP},code=sm_${COMPUTE_CAP} -Xptxas="-v" -Xcompiler $(CXXFLAGS)
🤖 Prompt for AI Agents
In the Makefile at line 41, the NVCCFLAGS variable includes the CXXFLAGS
variable inside quotes with -Xcompiler "${CXXFLAGS}", causing the entire
CXXFLAGS string to be treated as a single argument with embedded spaces. To fix
this, remove the quotes around ${CXXFLAGS} so that the flags are expanded as
separate arguments, changing -Xcompiler "${CXXFLAGS}" to -Xcompiler ${CXXFLAGS}.

This commit introduces a new, self-contained Makefile (`Makefile.mps`) for building the project with the MPS backend on macOS. This is a major refactoring of the build process to address the persistent linker errors that were occurring.

The new `Makefile.mps` explicitly defines all the necessary include paths, library paths, and libraries for the MPS build, making it independent of the main `Makefile` and less prone to errors.

The Makefiles in the subdirectories have also been simplified to only compile object files, with the `Makefile.mps` now responsible for creating the static libraries.

To build with MPS support, use the command: `make -f Makefile.mps`
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (6)
MpsKeySearchDevice/Makefile (1)

1-1: Add the missing test phony target for consistency and to silence lint warnings.
checkmake still reports the absence of a test target. Even if you don’t intend to wire unit tests here, declaring the target avoids accidental filename clashes and keeps all component Makefiles uniform.

-.PHONY: all clean
+.PHONY: all clean test
+
+test:
+	@echo "No component-specific tests defined for $(NAME)"
util/Makefile (1)

1-1: Declare a test phony target to match project-wide convention.

-.PHONY: all clean
+.PHONY: all clean test
+
+test:
+	@echo "No tests for util/"
CmdParse/Makefile (1)

1-1: Add the standard test phony target.

Same rationale as other components—keeps lint quiet and targets uniform.

-.PHONY: all clean
+.PHONY: all clean test
+
+test:
+	@echo "No tests for CmdParse/"
Logger/Makefile (1)

1-1: Include a phony test target for consistency.

-.PHONY: all clean
+.PHONY: all clean test
+
+test:
+	@echo "No tests for Logger/"
secp256k1lib/Makefile (1)

1-1: Add the missing test phony target.

-.PHONY: all clean
+.PHONY: all clean test
+
+test:
+	@echo "No tests for secp256k1lib/"
Makefile.mps (1)

16-16: Consider making Homebrew paths configurable.

The hardcoded Homebrew paths assume a specific installation location that may not be universal across different macOS setups (Intel vs Apple Silicon, custom Homebrew prefix).

Consider detecting the Homebrew prefix dynamically:

-INCLUDE += -I/opt/homebrew/opt/openssl/include
+HOMEBREW_PREFIX?=$(shell brew --prefix 2>/dev/null || echo "/opt/homebrew")
+INCLUDE += -I$(HOMEBREW_PREFIX)/opt/openssl/include
-LDFLAGS=-L/opt/homebrew/opt/openssl/lib -L${LIBDIR} -L${LIBTORCH_LIB}
+LDFLAGS=-L$(HOMEBREW_PREFIX)/opt/openssl/lib -L${LIBDIR} -L${LIBTORCH_LIB}

Also applies to: 28-28

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 39468d9 and deba942.

📒 Files selected for processing (9)
  • AddressUtil/Makefile (1 hunks)
  • CmdParse/Makefile (1 hunks)
  • CryptoUtil/Makefile (1 hunks)
  • KeyFinderLib/Makefile (1 hunks)
  • Logger/Makefile (1 hunks)
  • Makefile.mps (1 hunks)
  • MpsKeySearchDevice/Makefile (1 hunks)
  • secp256k1lib/Makefile (1 hunks)
  • util/Makefile (1 hunks)
🧰 Additional context used
🪛 checkmake (0.2.2)
AddressUtil/Makefile

[warning] 1-1: Missing required phony target "test"

(minphony)

Logger/Makefile

[warning] 1-1: Missing required phony target "test"

(minphony)

CmdParse/Makefile

[warning] 1-1: Missing required phony target "test"

(minphony)

secp256k1lib/Makefile

[warning] 1-1: Missing required phony target "test"

(minphony)

util/Makefile

[warning] 1-1: Missing required phony target "test"

(minphony)

MpsKeySearchDevice/Makefile

[warning] 1-1: Missing required phony target "test"

(minphony)

CryptoUtil/Makefile

[warning] 1-1: Missing required phony target "test"

(minphony)

KeyFinderLib/Makefile

[warning] 1-1: Missing required phony target "test"

(minphony)

🔇 Additional comments (11)
MpsKeySearchDevice/Makefile (1)

6-9: Verify whether an archive or binary should be produced.
all currently stops at object files. Earlier revisions created a static lib (libMpsKeySearchDevice.a) which downstream link steps may still expect. Double-check the top-level build to ensure:

  1. Nothing depends on a missing archive.
  2. Linker command-lines were updated accordingly.

If an archive is still required, add:

all: lib$(NAME).a

lib$(NAME).a: $(OBJS)
	$(AR) rcs $@ $^
util/Makefile (1)

6-9: Confirm removal of static-library creation doesn’t break dependants.
The previous Makefile produced libutil.a. With the archive step gone, any component that links -lutil will now fail. Ensure either:

  • Down-stream Makefiles were updated to link object files directly, or
  • The archive rule is reinstated.
CmdParse/Makefile (1)

6-9: Double-check consumers of libcmdparse.a.

Dropping the archive step may break link lines such as -lcmdparse. Verify build passes end-to-end or restore:

all: libcmdparse.a

libcmdparse.a: $(OBJS)
	$(AR) rcs $@ $^
Logger/Makefile (1)

6-9: Ensure the build still links without liblogger.a.

If other modules still expect the static library, re-introduce the archive rule or update their link flags.

secp256k1lib/Makefile (1)

6-9: Validate link expectations after dropping libsecp256k1.a.

Downstream code commonly links against a secp256k1 archive. Removing it may break the final link step; confirm or restore.

CryptoUtil/Makefile (1)

1-12: LGTM! Clean Makefile refactoring.

The refactoring from explicit compilation loops to pattern rules is well-executed. The addition of .PHONY declarations, the OBJS variable derivation, and the simplified build structure all follow Makefile best practices.

AddressUtil/Makefile (1)

1-12: LGTM! Consistent refactoring pattern.

This Makefile follows the exact same refactoring pattern as other components, which ensures build system consistency across the project. The pattern rule and variable structure are correctly implemented.

KeyFinderLib/Makefile (1)

1-12: LGTM! Simplified and consistent build structure.

The refactoring maintains consistency with other Makefiles while appropriately removing CUDA-specific build artifacts. The simplified clean target and pattern rule implementation are correct.

Makefile.mps (3)

56-57: LGTM! Well-structured executable build target.

The executable build correctly depends on libraries and uses appropriate compiler and linker flags. The main source files are properly specified.


60-72: LGTM! Comprehensive clean target.

The clean target properly cleans all component directories and removes output directories. The .PHONY declaration is correctly specified.


37-40: Double-check the library build rule applies correctly to all $(LIBDIR)/lib%.a targets

I confirmed that each source directory exists and you’ve declared a static target for every library, but the .SECONDEXPANSION pattern is tricky—please verify:

  • That lib%.a: actually matches $(LIBDIR)/libname.a (if LIBDIR isn’t empty, the rule may never fire).
  • That $(addprefix $*, $(notdir $@)) yields the intended object files (it should expand to something like foo.o, not raw .cpp or garbled names).
  • That running make libs produces archives containing the correct .o files (and that ar rvs is invoked with object files, not sources).

Makefile.mps Outdated
INCLUDE += -I/opt/homebrew/opt/openssl/include

# Libtorch paths
LIBTORCH_HOME?=/Users/haq/miniconda3/lib/python3.12/site-packages/torch
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Make Libtorch path configurable instead of hardcoded.

The hardcoded path /Users/haq/miniconda3/lib/python3.12/site-packages/torch makes the build system non-portable and will fail on other developer machines.

Consider this approach to make it configurable:

-LIBTORCH_HOME?=/Users/haq/miniconda3/lib/python3.12/site-packages/torch
+LIBTORCH_HOME?=$(shell python3 -c "import torch; print(torch.__path__[0])" 2>/dev/null || echo "/usr/local/lib/python3.12/site-packages/torch")

Or provide clear documentation on how to set LIBTORCH_HOME environment variable.

🤖 Prompt for AI Agents
In Makefile.mps at line 19, the LIBTORCH_HOME path is hardcoded, reducing
portability. Modify the Makefile to allow LIBTORCH_HOME to be set via an
environment variable or a command-line argument, falling back to a default only
if not provided. Additionally, add documentation or comments explaining how to
set LIBTORCH_HOME externally to ensure other developers can configure it
correctly.

This commit fixes a runtime error on macOS where the `mpsBitCrack` executable could not find the `libtorch.dylib` library.

The `Makefile.mps` has been updated to include the `-rpath` linker flag, which embeds the path to the torch libraries in the executable. This allows the dynamic linker to find the required libraries at runtime.
This commit fixes an issue where the `BUILD_MPS` preprocessor flag was not being defined when compiling the `mpsBitCrack` executable using `Makefile.mps`. This caused all the MPS-related code to be excluded from the build, resulting in no MPS device being detected at runtime.

The `CXXFLAGS` in `Makefile.mps` has been updated to include the `-DBUILD_MPS` flag.
This commit introduces a new, simplified Makefile (`Makefile.mps_simple`) for building the project with the MPS backend on macOS. This is intended to be a more robust and easier-to-debug alternative to the complex, multi-level Makefiles that were causing persistent linker errors.

The new `Makefile.mps_simple` is completely self-contained and explicitly defines all the necessary include paths, library paths, and libraries for the MPS build.

To build with MPS support, use the command: `make -f Makefile.mps_simple`
This commit introduces an experimental backend for Apple Silicon using Apple's Metal framework. This is intended to allow BitCrack to run on Apple M-series GPUs.

This commit includes:
- A new `MetalKeySearchDevice` class that implements the `KeySearchDevice` interface.
- A new `keysearch.metal` file containing the `secp256k1` cryptographic kernels written in Metal Shading Language.
- A new `Makefile.metal` that is specifically designed to build the project with the Metal backend on macOS.

To build with Metal support, use the command: `make -f Makefile.metal`

Note: This code has not been compiled or tested on an Apple Silicon machine. You will need to have the Xcode toolchain installed.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

♻️ Duplicate comments (1)
Makefile (1)

14-14: Verify LDFLAGS usage

Based on past review comments, LDFLAGS was identified as unused. If it's still not referenced anywhere in the build system, consider removing it to avoid confusion.

#!/bin/bash
# Check if LDFLAGS is used anywhere in the makefiles
rg -t make '\$\(LDFLAGS\)' --glob '*/Makefile' --glob 'Makefile'
🧹 Nitpick comments (3)
MetalKeySearchDevice/MetalKeySearchDevice.cpp (2)

95-95: Incomplete implementation of core functionality

Several critical methods are not implemented:

  • Result checking after GPU computation (line 95)
  • Target setting for address matching
  • Result retrieval
  • Next key tracking

These need to be implemented for the device to function properly.

Would you like me to help implement the missing functionality for result checking and target matching?

Also applies to: 105-110, 125-127


120-123: Implement Metal device memory querying

The memory info method returns zeros. Metal provides APIs to query device memory.

 void MetalKeySearchDevice::getMemoryInfo(uint64_t &freeMem, uint64_t &totalMem) {
-    freeMem = 0;
-    totalMem = 0;
+    // Metal doesn't provide direct memory queries like CUDA
+    // Use recommended memory limit as approximation
+    totalMem = _device->recommendedMaxWorkingSetSize();
+    // Free memory estimation not directly available
+    freeMem = totalMem / 2; // Conservative estimate
 }
MetalKeySearchDevice/keysearch.metal (1)

135-136: Improve readability with constant definitions

The code repeatedly constructs uint256_t from the _P array inline.

+// Define constant for modulus P
+constant uint256_t P_CONST = {
+    _P[0], _P[1], _P[2], _P[3], _P[4], _P[5], _P[6], _P[7]
+};
+
 uint256_t subModP256k(uint256_t a, uint256_t b) {
     uint borrow = 0;
     uint256_t c = sub256k(a, b, &borrow);
     if (borrow) {
         uint carry = 0;
-        add256k(c, (uint256_t){_P[0], _P[1], _P[2], _P[3], _P[4], _P[5], _P[6], _P[7]}, &carry);
+        add256k(c, P_CONST, &carry);
     }
     return c;
 }

Also applies to: 145-146

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between abe8da6 and 7f0db08.

📒 Files selected for processing (9)
  • KeyFinder/DeviceManager.cpp (2 hunks)
  • KeyFinder/DeviceManager.h (1 hunks)
  • KeyFinder/Makefile (1 hunks)
  • KeyFinder/main.cpp (2 hunks)
  • Makefile (6 hunks)
  • MetalKeySearchDevice/Makefile (1 hunks)
  • MetalKeySearchDevice/MetalKeySearchDevice.cpp (1 hunks)
  • MetalKeySearchDevice/MetalKeySearchDevice.h (1 hunks)
  • MetalKeySearchDevice/keysearch.metal (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • KeyFinder/Makefile
🚧 Files skipped from review as they are similar to previous changes (3)
  • KeyFinder/DeviceManager.h
  • KeyFinder/main.cpp
  • KeyFinder/DeviceManager.cpp
🧰 Additional context used
🧬 Code Graph Analysis (2)
MetalKeySearchDevice/MetalKeySearchDevice.h (3)
KeyFinderLib/KeySearchDevice.h (1)
  • KeySearchDevice (37-63)
KeyFinderLib/KeySearchTypes.h (1)
  • KeySearchTarget (40-94)
secp256k1lib/secp256k1.h (2)
  • uint256 (12-274)
  • secp256k1 (10-373)
MetalKeySearchDevice/MetalKeySearchDevice.cpp (3)
MetalKeySearchDevice/MetalKeySearchDevice.h (1)
  • MetalKeySearchDevice (7-33)
KeyFinderLib/KeySearchDevice.h (1)
  • KeySearchException (10-25)
secp256k1lib/secp256k1.h (1)
  • uint256 (12-274)
🪛 checkmake (0.2.2)
MetalKeySearchDevice/Makefile

[warning] 1-1: Missing required phony target "test"

(minphony)

🔇 Additional comments (4)
MetalKeySearchDevice/Makefile (1)

1-13: LGTM!

The Makefile follows standard conventions with proper phony targets and pattern rules. The static analysis warning about missing "test" target can be safely ignored as it's not required for all components.

Makefile (2)

58-63: Metal build configuration looks good

The Metal build setup correctly:

  • Switches to clang++ compiler (required for Metal)
  • Updates to C++17 standard
  • Adds necessary Metal and Foundation frameworks
  • Suppresses unused parameter warnings

3-3: Metal integration properly structured

The Metal device is correctly integrated into the build system with:

  • Addition to DIRS list for includes
  • Dedicated build target with proper dependencies
  • Conditional inclusion in KEYFINDER_DEPS

Also applies to: 73-75, 101-103

MetalKeySearchDevice/MetalKeySearchDevice.h (1)

1-35: Well-structured Metal device header

The header file is properly designed with:

  • Correct header guards
  • Appropriate Metal-cpp pointer types for Metal objects
  • Proper inheritance from KeySearchDevice base class
  • Complete virtual function declarations matching the interface

Comment on lines +150 to +158
uint256_t mulModP256k(uint256_t a, uint256_t b) {
uint256_t high, low;
multiply256(a, b, &high, &low);

// This is a simplified version of the modular reduction from the OpenCL code.
// A full implementation is required for correctness.
// For now, just return the low part of the product.
return low;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Incomplete modular arithmetic implementations

The modular multiplication and inverse functions are marked as simplified and will produce incorrect results.

These functions are critical for correctness. The modular multiplication needs proper Montgomery reduction for secp256k1, and the inverse needs to implement the extended Euclidean algorithm or Fermat's little theorem properly.

Would you like me to provide complete implementations of mulModP256k and invModP256k for secp256k1?

Also applies to: 165-168

🤖 Prompt for AI Agents
In MetalKeySearchDevice/keysearch.metal around lines 150 to 158 and 165 to 168,
the modular multiplication and inverse functions are currently simplified and
incorrect. Replace the simplified modular multiplication with a full Montgomery
reduction implementation tailored for secp256k1 to ensure correct modular
arithmetic. Similarly, implement the modular inverse function using the extended
Euclidean algorithm or Fermat's little theorem for accurate results. This will
ensure both functions perform correct modular operations as required.

Comment on lines +183 to +184
if (equal(*p1x, p2x)) {
if (equal(*p1y, p2y)) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Function used before definition

The equal function is called on lines 183-184 but defined later at line 239. Metal requires functions to be defined before use.

Move the equal function definition before the point_add function:

+bool equal(uint256_t a, uint256_t b) {
+    for (int i = 0; i < 8; i++) {
+        if (a.v[i] != b.v[i]) {
+            return false;
+        }
+    }
+    return true;
+}
+
 void point_add(thread uint256_t* p1x, thread uint256_t* p1y, uint256_t p2x, uint256_t p2y, thread uint256_t* p3x, thread uint256_t* p3y) {

Also applies to: 239-246

🤖 Prompt for AI Agents
In MetalKeySearchDevice/keysearch.metal between lines 183 and 184, the function
'equal' is used before its definition at line 239, which Metal does not allow.
To fix this, move the entire 'equal' function definition so that it appears
before the 'point_add' function where it is first called. Also apply this change
to the function defined at lines 239-246 to ensure all functions are defined
before use.

Comment on lines +227 to +233
uint256_t tx, ty;
for (int i = 0; i < 256; i++) {
if ((private_key.v[7 - i / 32] >> (i % 32)) & 1) {
point_add(&px, &py, tx, ty, &px, &py);
}
point_add(&tx, &ty, tx, ty, &tx, &ty);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Uninitialized variables and incorrect scalar multiplication

The variables tx and ty are used without initialization, and the scalar multiplication algorithm is incorrect.

The double-and-add algorithm needs proper initialization and logic:

-    uint256_t tx, ty;
+    // Initialize result to infinity (identity element)
+    uint256_t rx = { _INFINITY[0], _INFINITY[1], _INFINITY[2], _INFINITY[3], _INFINITY[4], _INFINITY[5], _INFINITY[6], _INFINITY[7] };
+    uint256_t ry = { _INFINITY[0], _INFINITY[1], _INFINITY[2], _INFINITY[3], _INFINITY[4], _INFINITY[5], _INFINITY[6], _INFINITY[7] };
+    
+    // Current point being doubled
+    uint256_t qx = px;
+    uint256_t qy = py;
+    
     for (int i = 0; i < 256; i++) {
         if ((private_key.v[7 - i / 32] >> (i % 32)) & 1) {
-            point_add(&px, &py, tx, ty, &px, &py);
+            point_add(&rx, &ry, qx, qy, &rx, &ry);
         }
-        point_add(&tx, &ty, tx, ty, &tx, &ty);
+        // Double the current point
+        point_add(&qx, &qy, qx, qy, &qx, &qy);
     }
+    
+    px = rx;
+    py = ry;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
uint256_t tx, ty;
for (int i = 0; i < 256; i++) {
if ((private_key.v[7 - i / 32] >> (i % 32)) & 1) {
point_add(&px, &py, tx, ty, &px, &py);
}
point_add(&tx, &ty, tx, ty, &tx, &ty);
}
// Initialize result to infinity (identity element)
uint256_t rx = {
_INFINITY[0], _INFINITY[1], _INFINITY[2], _INFINITY[3],
_INFINITY[4], _INFINITY[5], _INFINITY[6], _INFINITY[7]
};
uint256_t ry = {
_INFINITY[0], _INFINITY[1], _INFINITY[2], _INFINITY[3],
_INFINITY[4], _INFINITY[5], _INFINITY[6], _INFINITY[7]
};
// Current point being doubled
uint256_t qx = px;
uint256_t qy = py;
for (int i = 0; i < 256; i++) {
if ((private_key.v[7 - i / 32] >> (i % 32)) & 1) {
point_add(&rx, &ry, qx, qy, &rx, &ry);
}
// Double the current point
point_add(&qx, &qy, qx, qy, &qx, &qy);
}
px = rx;
py = ry;
🤖 Prompt for AI Agents
In MetalKeySearchDevice/keysearch.metal around lines 227 to 233, the variables
tx and ty are used without initialization, and the scalar multiplication logic
is incorrect. Initialize tx and ty to the base point coordinates before the loop
starts. Then, implement the double-and-add algorithm correctly by iterating over
each bit of the private key, doubling the current point each iteration, and
adding the base point to the result only when the corresponding bit is set.
Adjust the point_add calls accordingly to reflect this logic.

Comment on lines +61 to +69
MTL::Buffer* privateKeysBuffer = _device->newBuffer(_keysPerStep * sizeof(uint256_t), MTL::ResourceStorageModeShared);
MTL::Buffer* publicKeysXBuffer = _device->newBuffer(_keysPerStep * sizeof(uint256_t), MTL::ResourceStorageModeShared);
MTL::Buffer* publicKeysYBuffer = _device->newBuffer(_keysPerStep * sizeof(uint256_t), MTL::ResourceStorageModeShared);

// Generate private keys
uint256_t* privateKeys = (uint256_t*)privateKeysBuffer->contents();
for (uint64_t i = 0; i < _keysPerStep; i++) {
privateKeys[i] = _startKey + _stride * i;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Type mismatch: use secp256k1::uint256 instead of uint256_t

The code uses uint256_t which doesn't match the Metal shader's struct definition. The private key arithmetic should use secp256k1::uint256 and properly handle the conversion to the shader's format.

The buffer allocation and private key generation need to be rewritten to:

  1. Define a proper struct matching the Metal shader's uint256_t
  2. Convert from secp256k1::uint256 to the shader format
  3. Ensure proper memory layout compatibility
+    // Define struct matching Metal shader
+    struct metal_uint256_t {
+        uint32_t v[8];
+    };
+
     // Create buffers
-    MTL::Buffer* privateKeysBuffer = _device->newBuffer(_keysPerStep * sizeof(uint256_t), MTL::ResourceStorageModeShared);
-    MTL::Buffer* publicKeysXBuffer = _device->newBuffer(_keysPerStep * sizeof(uint256_t), MTL::ResourceStorageModeShared);
-    MTL::Buffer* publicKeysYBuffer = _device->newBuffer(_keysPerStep * sizeof(uint256_t), MTL::ResourceStorageModeShared);
+    MTL::Buffer* privateKeysBuffer = _device->newBuffer(_keysPerStep * sizeof(metal_uint256_t), MTL::ResourceStorageModeShared);
+    MTL::Buffer* publicKeysXBuffer = _device->newBuffer(_keysPerStep * sizeof(metal_uint256_t), MTL::ResourceStorageModeShared);
+    MTL::Buffer* publicKeysYBuffer = _device->newBuffer(_keysPerStep * sizeof(metal_uint256_t), MTL::ResourceStorageModeShared);

     // Generate private keys
-    uint256_t* privateKeys = (uint256_t*)privateKeysBuffer->contents();
+    metal_uint256_t* privateKeys = (metal_uint256_t*)privateKeysBuffer->contents();
     for (uint64_t i = 0; i < _keysPerStep; i++) {
-        privateKeys[i] = _startKey + _stride * i;
+        secp256k1::uint256 key = _startKey + _stride * i;
+        // Convert secp256k1::uint256 to metal_uint256_t
+        for (int j = 0; j < 8; j++) {
+            privateKeys[i].v[j] = key.v[j];
+        }
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
MTL::Buffer* privateKeysBuffer = _device->newBuffer(_keysPerStep * sizeof(uint256_t), MTL::ResourceStorageModeShared);
MTL::Buffer* publicKeysXBuffer = _device->newBuffer(_keysPerStep * sizeof(uint256_t), MTL::ResourceStorageModeShared);
MTL::Buffer* publicKeysYBuffer = _device->newBuffer(_keysPerStep * sizeof(uint256_t), MTL::ResourceStorageModeShared);
// Generate private keys
uint256_t* privateKeys = (uint256_t*)privateKeysBuffer->contents();
for (uint64_t i = 0; i < _keysPerStep; i++) {
privateKeys[i] = _startKey + _stride * i;
}
// Define struct matching Metal shader
struct metal_uint256_t {
uint32_t v[8];
};
// Create buffers
MTL::Buffer* privateKeysBuffer = _device->newBuffer(_keysPerStep * sizeof(metal_uint256_t), MTL::ResourceStorageModeShared);
MTL::Buffer* publicKeysXBuffer = _device->newBuffer(_keysPerStep * sizeof(metal_uint256_t), MTL::ResourceStorageModeShared);
MTL::Buffer* publicKeysYBuffer = _device->newBuffer(_keysPerStep * sizeof(metal_uint256_t), MTL::ResourceStorageModeShared);
// Generate private keys
metal_uint256_t* privateKeys = (metal_uint256_t*)privateKeysBuffer->contents();
for (uint64_t i = 0; i < _keysPerStep; i++) {
secp256k1::uint256 key = _startKey + _stride * i;
// Convert secp256k1::uint256 to metal_uint256_t
for (int j = 0; j < 8; j++) {
privateKeys[i].v[j] = key.v[j];
}
}
🤖 Prompt for AI Agents
In MetalKeySearchDevice/MetalKeySearchDevice.cpp around lines 61 to 69, replace
the use of uint256_t with secp256k1::uint256 for private key arithmetic to match
the Metal shader's struct definition. Define a struct that matches the shader's
uint256_t layout, convert each secp256k1::uint256 private key to this struct
format before storing it in the buffer, and ensure the buffer memory layout
aligns with the shader expectations for correct data interpretation.


// Create a command buffer
MTL::CommandBuffer* commandBuffer = _commandQueue->commandBuffer();
MTL::ComputeCommandEncoder*- commandEncoder = commandBuffer->computeCommandEncoder();
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix syntax error in variable declaration

There's a syntax error with an errant dash character in the variable name.

-    MTL::ComputeCommandEncoder*- commandEncoder = commandBuffer->computeCommandEncoder();
+    MTL::ComputeCommandEncoder* commandEncoder = commandBuffer->computeCommandEncoder();
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
MTL::ComputeCommandEncoder*- commandEncoder = commandBuffer->computeCommandEncoder();
MTL::ComputeCommandEncoder* commandEncoder = commandBuffer->computeCommandEncoder();
🤖 Prompt for AI Agents
In MetalKeySearchDevice/MetalKeySearchDevice.cpp at line 73, the variable
declaration for commandEncoder contains an incorrect dash character before the
variable name. Remove the dash so that the declaration correctly reads as a
pointer to MTL::ComputeCommandEncoder named commandEncoder without any
extraneous characters.

Comment on lines +112 to +114
uint64_t MetalKeySearchDevice::keysPerStep() {
return 0;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Return actual keys per step value

The method returns 0 instead of the stored _keysPerStep value.

 uint64_t MetalKeySearchDevice::keysPerStep() {
-    return 0;
+    return _keysPerStep;
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
uint64_t MetalKeySearchDevice::keysPerStep() {
return 0;
}
uint64_t MetalKeySearchDevice::keysPerStep() {
return _keysPerStep;
}
🤖 Prompt for AI Agents
In MetalKeySearchDevice/MetalKeySearchDevice.cpp at lines 112 to 114, the
keysPerStep() method incorrectly returns 0 instead of the actual stored value.
Modify the method to return the member variable _keysPerStep instead of 0 to
reflect the correct number of keys per step.

This commit adds the `Makefile.metal` file, which is a self-contained Makefile for building the project with the Metal backend on macOS.

This Makefile is intended to provide a more robust and easier-to-debug build process than the previous approach of modifying the main Makefile.

To build with Metal support, use the command: `make -f Makefile.metal`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant