Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/publish-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ jobs:
./lib
./nitrogen
./node_modules/.yarn-state.yml
./cpp/botan_generated

publish-npm-dry-run:
needs: publish-release
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -85,5 +85,8 @@ android/generated
# React Native Nitro Modules
nitrogen/

# Botan generated files
cpp/botan_generated/

# Eslint
.eslintcache
5 changes: 5 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,8 @@
url = https://github.com/bitcoin-core/secp256k1.git
# Pinned to commit: a660a4976efe880bae7982ee410b9e0dc59ac983 (v0.7.0)
# DO NOT UPDATE without explicit approval - this affects cryptographic operations
[submodule "cpp/botan"]
path = cpp/botan
url = https://github.com/randombit/botan.git
# Pinned to commit: 07e1cfe0a06b224bbb37ad534736924931184246 (v3.9.0)
# DO NOT UPDATE without explicit approval - this affects cryptographic operations
11 changes: 8 additions & 3 deletions NativeUtils.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Pod::Spec.new do |s|
"cpp/*.{hpp,cpp}",
"cpp/*.{h,c}",
"cpp/secp256k1/src/*.{h,c}",
"cpp/botan_conditional.cpp", # Botan conditional compilation
]

s.exclude_files = [
Expand All @@ -35,21 +36,25 @@ Pod::Spec.new do |s|
"cpp/secp256k1/src/selftest.h",
"cpp/secp256k1/src/**/tests_impl.h",
"cpp/secp256k1/src/**/bench_impl.h",
# Exclude Botan submodule (we use generated amalgamation files)
"cpp/botan/**/*",
]

s.public_header_files = [
"cpp/secp256k1/include/secp256k1.h",
"cpp/botan_conditional.h", # Botan conditional header
]

s.header_dir = "secp256k1"
s.header_mappings_dir = "cpp/secp256k1/include"

s.pod_target_xcconfig = {
# C++ compiler flags, mainly for folly.
# C++ compiler flags, mainly for folly and Botan
"GCC_PREPROCESSOR_DEFINITIONS" => "$(inherited) FOLLY_NO_CONFIG FOLLY_CFG_NO_COROUTINES USE_ECMULT_STATIC_PRECOMPUTATION USE_FIELD_10X26 USE_SCALAR_8X32 ECMULT_WINDOW_SIZE=15 ECMULT_GEN_PREC_BITS=4",
"HEADER_SEARCH_PATHS" => "$(inherited) $(PODS_TARGET_SRCROOT)/cpp/secp256k1 $(PODS_TARGET_SRCROOT)/cpp/secp256k1/include $(PODS_TARGET_SRCROOT)/cpp/secp256k1/src",
"HEADER_SEARCH_PATHS" => "$(inherited) $(PODS_TARGET_SRCROOT)/cpp $(PODS_TARGET_SRCROOT)/cpp/botan_generated $(PODS_TARGET_SRCROOT)/cpp/secp256k1 $(PODS_TARGET_SRCROOT)/cpp/secp256k1/include $(PODS_TARGET_SRCROOT)/cpp/secp256k1/src",
"OTHER_CFLAGS" => "$(inherited) -DUSE_ECMULT_STATIC_PRECOMPUTATION -DUSE_FIELD_10X26 -DUSE_SCALAR_8X32 -DECMULT_WINDOW_SIZE=15 -DECMULT_GEN_PREC_BITS=4",
"CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES" => "YES"
"CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES" => "YES",
"GCC_SYMBOLS_PRIVATE_EXTERN" => "YES" # Hide symbols for clean API
}

s.dependency 'React-jsi'
Expand Down
14 changes: 12 additions & 2 deletions SUBMODULES.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,26 @@ This file documents the exact commit hashes for all Git submodules used in this
- **Reason**: Latest stable commit with security fixes
- **⚠️ WARNING**: Do not update without security review - affects cryptographic operations

## cpp/botan

- **Repository**: https://github.com/randombit/botan.git
- **Pinned Commit**: `07e1cfe0a06b224bbb37ad534736924931184246`
- **Version**: v3.9.0
- **Date Pinned**: 2025-09-18
- **Reason**: Latest stable release
- **⚠️ WARNING**: Do not update without security review - affects cryptographic operations

## Updating Submodules

To update a submodule:

1. Navigate to the submodule directory: `cd cpp/secp256k1`
1. Navigate to the submodule directory: `cd cpp/<submodule-name>`
2. Fetch latest changes: `git fetch origin`
3. Check out desired commit: `git checkout <new-commit-hash>`
4. Return to root: `cd ../..`
5. Update this documentation file
6. Commit the changes: `git add . && git commit -m "Update secp256k1 to <new-commit-hash>"`
6. Update scripts/verify-submodules.sh with the new expected commit hash
7. Commit the changes: `git add . && git commit -m "Update <submodule-name> to <new-commit-hash>"`

## Verification

Expand Down
9 changes: 8 additions & 1 deletion android/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,14 @@ add_library(${PACKAGE_NAME} SHARED
src/main/cpp/cpp-adapter.cpp
../cpp/HybridNativeUtils.cpp
../cpp/hex_utils.cpp
../cpp/botan_conditional.cpp
)

# Add Nitrogen specs :)
include(${CMAKE_SOURCE_DIR}/../nitrogen/generated/android/metamask_nativeutils+autolinking.cmake)

# Set up local includes
include_directories("src/main/cpp" "../cpp" "../cpp/secp256k1/include" "../cpp/secp256k1/src")
include_directories("src/main/cpp" "../cpp" "../cpp/botan_generated" "../cpp/secp256k1/include" "../cpp/secp256k1/src")

find_library(LOG_LIB log)

Expand All @@ -44,3 +45,9 @@ target_link_libraries(
${LOG_LIB}
android # <-- Android core
)

# Hide symbols for clean API and better performance
set_target_properties(${PACKAGE_NAME} PROPERTIES
CXX_VISIBILITY_PRESET hidden
VISIBILITY_INLINES_HIDDEN ON
)
1 change: 1 addition & 0 deletions cpp/botan
Submodule botan added at 07e1cf
42 changes: 42 additions & 0 deletions cpp/botan_conditional.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Conditional Botan implementation inclusion
// This file automatically includes the appropriate Botan implementation based on target architecture

#include "botan_conditional.h"

// Include the appropriate implementation based on architecture detection
#if defined(__APPLE__)
#include <TargetConditionals.h>
#if TARGET_OS_IOS
// iOS device or simulator
#if defined(__aarch64__) || defined(_M_ARM64)
// iOS ARM64 (physical devices) - hardware accelerated
#include "botan_generated/botan_ios_arm64.cpp"
#else
// iOS simulator (x86_64) - portable implementation
#include "botan_generated/botan_generic.cpp"
#endif
#else
// macOS
#if defined(__aarch64__) || defined(_M_ARM64)
// Apple Silicon Mac - use iOS ARM64 optimized build
#include "botan_generated/botan_ios_arm64.cpp"
#else
// Intel Mac - portable implementation
#include "botan_generated/botan_generic.cpp"
#endif
#endif
#elif defined(__ANDROID__)
// Android platform
#if defined(__aarch64__) || defined(_M_ARM64)
// Android ARM64 (arm64-v8a) - hardware accelerated
#include "botan_generated/botan_android_arm64.cpp"
#else
// Android other architectures - portable implementation
#include "botan_generated/botan_generic.cpp"
#endif
#else
// Generic fallback for other platforms
#include "botan_generated/botan_generic.cpp"
#endif

// No global instances needed - everything is inline or compile-time
64 changes: 64 additions & 0 deletions cpp/botan_conditional.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#pragma once

// Architecture detection and conditional Botan inclusion
// This header automatically selects the optimal Botan build based on target architecture

// Platform and architecture detection
#if defined(__APPLE__)
#include <TargetConditionals.h>
#if TARGET_OS_IOS
// iOS device or simulator
#if defined(__aarch64__) || defined(_M_ARM64)
// iOS ARM64 (physical devices)
#include "botan_generated/botan_ios_arm64.h"
#define BOTAN_ARCH_OPTIMIZED 1
#define BOTAN_ARCH_NAME "iOS-ARM64-optimized"
#define BOTAN_PLATFORM "iOS"
#else
// iOS simulator (x86_64)
#include "botan_generated/botan_generic.h"
#define BOTAN_ARCH_OPTIMIZED 0
#define BOTAN_ARCH_NAME "iOS-Simulator-generic"
#define BOTAN_PLATFORM "iOS-Simulator"
#endif
#else
// macOS
#if defined(__aarch64__) || defined(_M_ARM64)
// Apple Silicon Mac
#include "botan_generated/botan_ios_arm64.h"
#define BOTAN_ARCH_OPTIMIZED 1
#define BOTAN_ARCH_NAME "macOS-ARM64-optimized"
#define BOTAN_PLATFORM "macOS"
#else
// Intel Mac
#include "botan_generated/botan_generic.h"
#define BOTAN_ARCH_OPTIMIZED 0
#define BOTAN_ARCH_NAME "macOS-Intel-generic"
#define BOTAN_PLATFORM "macOS"
#endif
#endif
#elif defined(__ANDROID__)
// Android platform
#if defined(__aarch64__) || defined(_M_ARM64)
// Android ARM64 (arm64-v8a)
#include "botan_generated/botan_android_arm64.h"
#define BOTAN_ARCH_OPTIMIZED 1
#define BOTAN_ARCH_NAME "Android-ARM64-optimized"
#define BOTAN_PLATFORM "Android"
#else
// Android other architectures (x86, x86_64, armeabi-v7a)
#include "botan_generated/botan_generic.h"
#define BOTAN_ARCH_OPTIMIZED 0
#define BOTAN_ARCH_NAME "Android-generic"
#define BOTAN_PLATFORM "Android"
#endif
#else
// Generic fallback for other platforms
#include "botan_generated/botan_generic.h"
#define BOTAN_ARCH_OPTIMIZED 0
#define BOTAN_ARCH_NAME "Generic-portable"
#define BOTAN_PLATFORM "Generic"
#endif

// Unified namespace - all Botan headers use the same namespace
using namespace Botan;
2 changes: 1 addition & 1 deletion example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"android:release": "react-native run-android --mode release",
"build:android": "react-native build-android --extra-params \"--no-daemon --console=plain -PreactNativeArchitectures=arm64-v8a\"",
"build:ios": "react-native build-ios --mode Debug",
"clean": "cd android && ./gradlew clean && cd ..",
"clean": "cd android && rm -rf .cxx && rm -rf build/ && ./gradlew clean && cd ..",
"ios": "react-native run-ios",
"ios:release": "react-native run-ios --mode release",
"start": "react-native start"
Expand Down
10 changes: 7 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"nitro.json",
"*.podspec",
"react-native.config.js",
"!cpp/botan",
"!ios/build",
"!android/build",
"!android/gradle",
Expand All @@ -55,11 +56,13 @@
"!cpp/secp256k1/**/*.md",
"!cpp/secp256k1/**/*.json",
"!cpp/secp256k1/**/*.sh",
"!cpp/secp256k1/**/*.py"
"!cpp/secp256k1/**/*.py",
"!cpp/botan/**/*"
],
"scripts": {
"build": "yarn nitrogen && yarn bob build",
"example": "cd example && yarn",
"build": "yarn nitrogen && yarn generate:botan && yarn bob build",
"generate:botan": "./scripts/build-botan.sh",
"postinstall": "yarn generate:botan",
"lint": "yarn lint:eslint && yarn lint:misc --check && yarn lint:dependencies --check && yarn lint:changelog",
"lint:changelog": "auto-changelog validate --prettier",
"lint:dependencies": "depcheck && yarn dedupe",
Expand Down Expand Up @@ -117,6 +120,7 @@
"nitro-codegen": true,
"react-native-nitro-modules": true,
"jest>@jest/core>jest-resolve>unrs-resolver": false,
"$root$": false
"nitro-codegen>react-native-nitro-modules": false
}
},
Expand Down
86 changes: 86 additions & 0 deletions scripts/build-botan.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#!/bin/bash

# Build script for generating Botan cpp files for different architectures
# This script creates optimized builds for iOS and Android target architectures

set -e # Exit on any error

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
BOTAN_DIR="$PROJECT_ROOT/cpp/botan"
BOTAN_GENERATED_DIR="$PROJECT_ROOT/cpp/botan_generated"
OUTPUT_DIR="$PROJECT_ROOT/cpp"

echo "🚀 Building Botan amalgamation files..."
echo "Project root: $PROJECT_ROOT"
echo "Botan directory: $BOTAN_DIR"
echo "Generated files directory: $BOTAN_GENERATED_DIR"
echo "Output directory: $OUTPUT_DIR"

# Create botan_generated directory if it doesn't exist
mkdir -p "$BOTAN_GENERATED_DIR"

# Configuration variables
BOTAN_MODULES="keccak,hmac,sha2_64"
COMMON_FLAGS="--amalgamation --minimized-build"

echo "📦 Using modules: $BOTAN_MODULES"

# Check if Botan submodule exists
if [ ! -d "$BOTAN_DIR" ]; then
echo "❌ Error: Botan submodule not found at $BOTAN_DIR"
echo "Please run: git submodule add https://github.com/randombit/botan.git cpp/botan"
exit 1
fi

# Navigate to Botan directory
cd "$BOTAN_DIR"

# Check if configure.py exists
if [ ! -f "configure.py" ]; then
echo "❌ Error: configure.py not found in Botan directory"
exit 1
fi

# Function to build Botan for a specific configuration
build_botan() {
local cpu_arch="$1"
local os_type="$2"
local build_name="$3"
local description="$4"

echo "$description"
./configure.py \
--cpu="$cpu_arch" \
--os="$os_type" \
$COMMON_FLAGS \
--enable-modules="$BOTAN_MODULES" \
--name-amalgamation="$build_name" \
--with-build-dir="$BOTAN_GENERATED_DIR"

# Check if files were generated in the botan directory
if [ ! -f "${build_name}.cpp" ] || [ ! -f "${build_name}.h" ]; then
echo "❌ Error: $build_name files not generated"
exit 1
fi

# Move generated files to botan_generated directory
mv "${build_name}.cpp" "$BOTAN_GENERATED_DIR/"
mv "${build_name}.h" "$BOTAN_GENERATED_DIR/"

echo "✅ $build_name files generated successfully"
}

# Build different configurations with proper OS flags
build_botan "armv8-a" "ios" "botan_ios_arm64" "📱 Generating iOS ARM64 optimized build..."
build_botan "arm64" "android" "botan_android_arm64" "🤖 Generating Android ARM64 optimized build..."
build_botan "generic" "generic" "botan_generic" "📟 Generating generic portable build (for simulators and x86)..."

# Remove build artifacts we don't need
rm -rf "$BOTAN_GENERATED_DIR/build"
rm -f "$BOTAN_GENERATED_DIR/Makefile"
rm -f "$BOTAN_GENERATED_DIR"/*.txt
rm -f "$BOTAN_GENERATED_DIR"/*.log

echo "✅ Botan amalgamation files generated successfully!"

17 changes: 17 additions & 0 deletions scripts/verify-submodules.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ echo "🔍 Verifying submodule commits..."

# Expected commits (update these when intentionally changing submodules)
EXPECTED_SECP256K1="a660a4976efe880bae7982ee410b9e0dc59ac983"
EXPECTED_BOTAN="07e1cfe0a06b224bbb37ad534736924931184246"

# Get actual commits
ACTUAL_SECP256K1=$(git ls-tree HEAD cpp/secp256k1 | awk '{print $3}')
ACTUAL_BOTAN=$(git ls-tree HEAD cpp/botan | awk '{print $3}')

# Verify secp256k1
if [ "$ACTUAL_SECP256K1" = "$EXPECTED_SECP256K1" ]; then
Expand All @@ -28,4 +30,19 @@ else
exit 1
fi

# Verify botan
if [ "$ACTUAL_BOTAN" = "$EXPECTED_BOTAN" ]; then
echo "✅ cpp/botan is correctly pinned to $EXPECTED_BOTAN"
else
echo "❌ cpp/botan commit mismatch!"
echo " Expected: $EXPECTED_BOTAN"
echo " Actual: $ACTUAL_BOTAN"
echo ""
echo "If this change is intentional:"
echo "1. Update EXPECTED_BOTAN in this script"
echo "2. Update SUBMODULES.md with the new commit hash"
echo "3. Ensure the change has been security reviewed"
exit 1
fi

echo "🎉 All submodules are correctly pinned!"
Loading