diff --git a/Makefile b/Makefile index 7d0579f9..838eb632 100644 --- a/Makefile +++ b/Makefile @@ -65,37 +65,55 @@ $(SECP256K1_LIB): secp256k1/configure fi @echo "x86_64 secp256k1 library built successfully" -# Build OpenSSL for x86_64 +# Build OpenSSL for x86_64 (minimal build optimized for curl) $(OPENSSL_LIB_SSL) $(OPENSSL_LIB_CRYPTO): openssl-3.4.2/Configure - @echo "Building OpenSSL for x86_64..." + @echo "Building minimal OpenSSL for x86_64 (optimized for curl)..." @cd openssl-3.4.2 && \ if [ ! -f ../openssl-install/lib64/libssl.a ] || [ ! -f ../openssl-install/lib64/libcrypto.a ]; then \ - echo "Configuring OpenSSL..."; \ + echo "Configuring minimal OpenSSL..."; \ make distclean >/dev/null 2>&1 || true; \ - ./Configure linux-x86_64 --prefix=$(PWD)/openssl-install --openssldir=$(PWD)/openssl-install/ssl no-shared no-dso; \ - echo "Building OpenSSL libraries..."; \ + ./Configure linux-x86_64 \ + --prefix=$(PWD)/openssl-install \ + --openssldir=$(PWD)/openssl-install/ssl \ + no-shared no-dso no-apps no-docs \ + no-ssl3 no-tls1 no-tls1_1 \ + no-engine no-comp no-legacy \ + no-gost no-idea no-seed no-md2 no-md4 \ + no-mdc2 no-rmd160 no-camellia no-rc5 \ + no-bf no-cast no-des \ + enable-tls1_2 enable-tls1_3; \ + echo "Building minimal OpenSSL libraries..."; \ make -j$(shell nproc 2>/dev/null || echo 4); \ make install_sw >/dev/null 2>&1; \ else \ echo "OpenSSL libraries already exist, skipping build"; \ fi - @echo "x86_64 OpenSSL libraries built successfully" + @echo "x86_64 minimal OpenSSL libraries built successfully" -# Build curl for x86_64 +# Build curl for x86_64 (minimal HTTPS-only build) $(CURL_LIB): curl-8.15.0/curl-8.15.0/configure $(OPENSSL_LIB_SSL) - @echo "Building curl for x86_64..." + @echo "Building minimal curl for x86_64 (HTTPS-only)..." @cd curl-8.15.0/curl-8.15.0 && \ if [ ! -f ../../curl-install/lib/libcurl.a ]; then \ - echo "Configuring curl..."; \ + echo "Configuring minimal curl..."; \ make distclean >/dev/null 2>&1 || true; \ - ./configure --prefix=$(PWD)/curl-install --with-openssl=$(PWD)/openssl-install --disable-shared --enable-static --without-libpsl --without-nghttp2 --without-brotli --without-zstd; \ - echo "Building curl library..."; \ + ./configure --prefix=$(PWD)/curl-install \ + --with-openssl=$(PWD)/openssl-install \ + --disable-shared --enable-static \ + --disable-ftp --disable-file --disable-ldap --disable-ldaps \ + --disable-pop3 --disable-imap --disable-smtp \ + --disable-gopher --disable-smb --disable-telnet \ + --disable-tftp --disable-dict --disable-rtsp \ + --disable-manual --disable-libcurl-option \ + --without-libpsl --without-nghttp2 --without-brotli --without-zstd \ + --without-libidn2 --without-librtmp --without-libssh2; \ + echo "Building minimal curl library..."; \ make -j$(shell nproc 2>/dev/null || echo 4); \ make install >/dev/null 2>&1; \ else \ echo "curl library already exists, skipping build"; \ fi - @echo "x86_64 curl library built successfully" + @echo "x86_64 minimal curl library built successfully" # Static library - includes secp256k1 and OpenSSL objects for self-contained library $(STATIC_LIB): $(LIB_OBJECTS) $(SECP256K1_LIB) $(OPENSSL_LIB_SSL) $(OPENSSL_LIB_CRYPTO) diff --git a/VERSION b/VERSION index a2e1aa9d..db7a4804 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.1.27 +0.1.31 diff --git a/build.sh b/build.sh index 05960ab3..d5ef46da 100755 --- a/build.sh +++ b/build.sh @@ -80,12 +80,60 @@ increment_version() { print_success "Updated VERSION file to ${NEW_VERSION#v}" } +# Function to perform git operations after successful build +perform_git_operations() { + local commit_message="$1" + + if [[ -z "$commit_message" ]]; then + return 0 # No commit message provided, skip git operations + fi + + print_status "Performing git operations..." + + # Check if we're in a git repository + if ! git rev-parse --git-dir > /dev/null 2>&1; then + print_warning "Not in a git repository - skipping git operations" + return 0 + fi + + # Check if there are changes to commit + if git diff --quiet && git diff --cached --quiet; then + print_warning "No changes to commit" + return 0 + fi + + # Add all changes + print_status "Adding changes to git..." + if ! git add .; then + print_error "Failed to add changes to git" + return 1 + fi + + # Commit changes + print_status "Committing changes with message: '$commit_message'" + if ! git commit -m "$commit_message"; then + print_error "Failed to commit changes" + return 1 + fi + + # Push changes + print_status "Pushing changes to remote repository..." + if ! git push; then + print_error "Failed to push changes to remote repository" + print_warning "Changes have been committed locally but not pushed" + return 1 + fi + + print_success "Git operations completed successfully!" + return 0 +} + # Function to show usage show_usage() { echo "NOSTR Core Library Build Script" echo "===============================" echo "" - echo "Usage: $0 [target] [architecture]" + echo "Usage: $0 [target] [-m \"commit message\"]" echo "" echo "Available targets:" echo " clean - Clean all build artifacts" @@ -99,6 +147,14 @@ show_usage() { echo " uninstall - Remove library from system" echo " help - Show this help message" echo "" + echo "Options:" + echo " -m \"message\" - Git commit message (triggers automatic git add, commit, push after successful build)" + echo "" + echo "Examples:" + echo " $0 lib -m \"Add new proof-of-work parameters\"" + echo " $0 x64 -m \"Fix OpenSSL minimal build configuration\"" + echo " $0 lib # Build without git operations" + echo "" echo "Library outputs (both self-contained with secp256k1):" echo " libnostr_core.a - x86_64 static library" echo " libnostr_core_arm64.a - ARM64 static library" @@ -109,7 +165,36 @@ show_usage() { } # Parse command line arguments -TARGET=${1:-lib} +TARGET="" +COMMIT_MESSAGE="" + +# Parse arguments +while [[ $# -gt 0 ]]; do + case $1 in + -m) + COMMIT_MESSAGE="$2" + shift 2 + ;; + -*) + print_error "Unknown option: $1" + show_usage + exit 1 + ;; + *) + if [[ -z "$TARGET" ]]; then + TARGET="$1" + else + print_error "Multiple targets specified: $TARGET and $1" + show_usage + exit 1 + fi + shift + ;; + esac +done + +# Set default target if none specified +TARGET=${TARGET:-lib} case "$TARGET" in clean) @@ -145,6 +230,7 @@ case "$TARGET" in if [ $SUCCESS -eq 2 ]; then print_success "Both architectures built successfully!" ls -la libnostr_core*.a + perform_git_operations "$COMMIT_MESSAGE" else print_error "Failed to build all libraries" exit 1 @@ -160,6 +246,7 @@ case "$TARGET" in SIZE=$(stat -c%s "libnostr_core.a") print_success "x64 static library built successfully (${SIZE} bytes)" ls -la libnostr_core.a + perform_git_operations "$COMMIT_MESSAGE" else print_error "Failed to build x64 static library" exit 1 @@ -175,6 +262,7 @@ case "$TARGET" in SIZE=$(stat -c%s "libnostr_core_arm64.a") print_success "ARM64 static library built successfully (${SIZE} bytes)" ls -la libnostr_core_arm64.a + perform_git_operations "$COMMIT_MESSAGE" else print_error "Failed to build ARM64 static library" exit 1 @@ -190,6 +278,7 @@ case "$TARGET" in SIZE=$(stat -c%s "libnostr_core.so") print_success "Shared library built successfully (${SIZE} bytes)" ls -la libnostr_core.so + perform_git_operations "$COMMIT_MESSAGE" else print_error "Failed to build shared library" exit 1 @@ -224,6 +313,7 @@ case "$TARGET" in print_success "All libraries and examples built successfully!" ls -la libnostr_core*.a ls -la examples/ + perform_git_operations "$COMMIT_MESSAGE" else print_error "Failed to build all components" exit 1 @@ -242,6 +332,7 @@ case "$TARGET" in print_success "Both libraries and examples built successfully" ls -la libnostr_core*.a ls -la examples/ + perform_git_operations "$COMMIT_MESSAGE" else print_error "Failed to build libraries for examples" exit 1 @@ -281,6 +372,7 @@ case "$TARGET" in make all sudo make install print_success "Library installed to /usr/local" + perform_git_operations "$COMMIT_MESSAGE" ;; uninstall) diff --git a/libnostr_core.a b/libnostr_core.a index e4626728..4b132684 100644 Binary files a/libnostr_core.a and b/libnostr_core.a differ diff --git a/nostr_core/core.c b/nostr_core/core.c index 29fa073d..7dba034e 100644 --- a/nostr_core/core.c +++ b/nostr_core/core.c @@ -1376,12 +1376,16 @@ static void replace_event_content(cJSON* target_event, cJSON* source_event) { * @param event The event to add proof of work to * @param private_key The private key for re-signing the event * @param target_difficulty Target number of leading zero bits (default: 4 if 0) + * @param max_attempts Maximum number of mining attempts (default: 10,000,000 if <= 0) + * @param progress_report_interval How often to call progress callback (default: 10,000 if <= 0) + * @param timestamp_update_interval How often to update timestamp (default: 10,000 if <= 0) * @param progress_callback Optional callback for mining progress * @param user_data User data for progress callback * @return NOSTR_SUCCESS on success, error code on failure */ int nostr_add_proof_of_work(cJSON* event, const unsigned char* private_key, - int target_difficulty, + int target_difficulty, int max_attempts, + int progress_report_interval, int timestamp_update_interval, void (*progress_callback)(int current_difficulty, uint64_t nonce, void* user_data), void* user_data) { if (!event || !private_key) { @@ -1398,6 +1402,17 @@ int nostr_add_proof_of_work(cJSON* event, const unsigned char* private_key, return NOSTR_SUCCESS; } + // Set default values for parameters + if (max_attempts <= 0) { + max_attempts = 10000000; // 10 million default + } + if (progress_report_interval <= 0) { + progress_report_interval = 10000; // Every 10,000 attempts + } + if (timestamp_update_interval <= 0) { + timestamp_update_interval = 10000; // Every 10,000 attempts + } + // Extract event data for reconstruction cJSON* kind_item = cJSON_GetObjectItem(event, "kind"); cJSON* content_item = cJSON_GetObjectItem(event, "content"); @@ -1414,7 +1429,6 @@ int nostr_add_proof_of_work(cJSON* event, const unsigned char* private_key, uint64_t nonce = 0; int attempts = 0; - int max_attempts = 10000000; time_t current_timestamp = original_timestamp; // PoW difficulty tracking variables @@ -1423,8 +1437,8 @@ int nostr_add_proof_of_work(cJSON* event, const unsigned char* private_key, // Mining loop while (attempts < max_attempts) { - // Update timestamp every 10,000 iterations - if (attempts % 10000 == 0) { + // Update timestamp based on timestamp_update_interval + if (attempts % timestamp_update_interval == 0) { current_timestamp = time(NULL); #ifdef ENABLE_DEBUG_LOGGING FILE* f = fopen("debug.log", "a"); @@ -1438,6 +1452,11 @@ int nostr_add_proof_of_work(cJSON* event, const unsigned char* private_key, best_difficulty_this_round = 0; } + // Call progress callback at specified intervals + if (progress_callback && (attempts % progress_report_interval == 0)) { + progress_callback(best_difficulty_overall, nonce, user_data); + } + // Create working copy of tags and add nonce cJSON* working_tags = cJSON_Duplicate(tags_item, 1); if (!working_tags) { @@ -1483,11 +1502,6 @@ int nostr_add_proof_of_work(cJSON* event, const unsigned char* private_key, best_difficulty_overall = current_difficulty; } - // Call progress callback if provided - if (progress_callback) { - progress_callback(current_difficulty, nonce, user_data); - } - // Check if we've reached the target if (current_difficulty >= target_difficulty) { #ifdef ENABLE_DEBUG_LOGGING diff --git a/nostr_core/core.o b/nostr_core/core.o index a76b0154..905d766d 100644 Binary files a/nostr_core/core.o and b/nostr_core/core.o differ diff --git a/nostr_core/nostr_core.h b/nostr_core/nostr_core.h index 6367f6ab..5786bc7e 100644 --- a/nostr_core/nostr_core.h +++ b/nostr_core/nostr_core.h @@ -485,13 +485,17 @@ int nostr_decode_npub(const char* input, unsigned char* private_key); * * @param event cJSON event object to add PoW to * @param private_key Private key for re-signing the event during mining - * @param target_difficulty Target number of leading zero bits (default: 2 if 0) - * @param progress_callback Optional callback for progress updates (nonce, difficulty, user_data) + * @param target_difficulty Target number of leading zero bits (default: 4 if 0) + * @param max_attempts Maximum number of mining attempts (default: 10,000,000 if <= 0) + * @param progress_report_interval How often to call progress callback (default: 10,000 if <= 0) + * @param timestamp_update_interval How often to update timestamp (default: 10,000 if <= 0) + * @param progress_callback Optional callback for progress updates (current_difficulty, nonce, user_data) * @param user_data User data passed to progress callback * @return NOSTR_SUCCESS on success, error code on failure */ int nostr_add_proof_of_work(cJSON* event, const unsigned char* private_key, - int target_difficulty, + int target_difficulty, int max_attempts, + int progress_report_interval, int timestamp_update_interval, void (*progress_callback)(int current_difficulty, uint64_t nonce, void* user_data), void* user_data); diff --git a/tests/test_pow_loop.c b/tests/test_pow_loop.c deleted file mode 100644 index 5afecc98..00000000 --- a/tests/test_pow_loop.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Manual Proof of Work Loop Test - * - * Creates an event and manually mines it by incrementing nonce - * until target difficulty is reached. Shows each iteration. - */ - -#include -#include -#include -#include "../nostr_core/nostr_core.h" -#include "../cjson/cJSON.h" - -// Helper function to count leading zero bits (from NIP-13) -static int zero_bits(unsigned char b) { - int n = 0; - - if (b == 0) - return 8; - - while (b >>= 1) - n++; - - return 7-n; -} - -// Count leading zero bits in hash (from NIP-13) -static int count_leading_zero_bits(unsigned char *hash) { - int bits, total, i; - for (i = 0, total = 0; i < 32; i++) { - bits = zero_bits(hash[i]); - total += bits; - if (bits != 8) - break; - } - return total; -} - -int main() { - // Initialize library - if (nostr_init() != NOSTR_SUCCESS) { - fprintf(stderr, "Failed to initialize nostr library\n"); - return 1; - } - - // Generate test keypair - unsigned char private_key[32]; - unsigned char public_key[32]; - - if (nostr_generate_keypair(private_key, public_key) != NOSTR_SUCCESS) { - fprintf(stderr, "Failed to generate keypair\n"); - nostr_cleanup(); - return 1; - } - - printf("=== Manual Proof of Work Mining (Target Difficulty: 8) ===\n\n"); - - // Create base event content - const char* content = "Proof of Work Test"; - int kind = 1; - time_t created_at = time(NULL); - - // Target difficulty - const int target_difficulty = 20; - uint64_t nonce = 0; - int max_attempts = 10000000000; - - printf("Mining event with target difficulty %d...\n\n", target_difficulty); - - // Mining loop - for (int attempt = 0; attempt < max_attempts; attempt++) { - // Create tags array with current nonce - cJSON* tags = cJSON_CreateArray(); - if (!tags) { - fprintf(stderr, "Failed to create tags array\n"); - break; - } - - // Add nonce tag: ["nonce", "", ""] - cJSON* nonce_tag = cJSON_CreateArray(); - char nonce_str[32]; - char difficulty_str[16]; - snprintf(nonce_str, sizeof(nonce_str), "%llu", (unsigned long long)nonce); - snprintf(difficulty_str, sizeof(difficulty_str), "%d", target_difficulty); - - cJSON_AddItemToArray(nonce_tag, cJSON_CreateString("nonce")); - cJSON_AddItemToArray(nonce_tag, cJSON_CreateString(nonce_str)); - cJSON_AddItemToArray(nonce_tag, cJSON_CreateString(difficulty_str)); - cJSON_AddItemToArray(tags, nonce_tag); - - // Create and sign event with current nonce - cJSON* event = nostr_create_and_sign_event(kind, content, tags, private_key, created_at); - cJSON_Delete(tags); - - if (!event) { - fprintf(stderr, "Failed to create event at nonce %llu\n", (unsigned long long)nonce); - nonce++; - continue; - } - - // Get event ID - cJSON* id_item = cJSON_GetObjectItem(event, "id"); - if (!id_item || !cJSON_IsString(id_item)) { - fprintf(stderr, "Failed to get event ID at nonce %llu\n", (unsigned long long)nonce); - cJSON_Delete(event); - nonce++; - continue; - } - - const char* event_id = cJSON_GetStringValue(id_item); - - // Convert hex ID to bytes and count leading zero bits - unsigned char hash[32]; - if (nostr_hex_to_bytes(event_id, hash, 32) != NOSTR_SUCCESS) { - fprintf(stderr, "Failed to convert event ID to bytes at nonce %llu\n", (unsigned long long)nonce); - cJSON_Delete(event); - nonce++; - continue; - } - - int current_difficulty = count_leading_zero_bits(hash); - - // Print current attempt - printf("Nonce %llu: ID = %.16s... (difficulty: %d)", - (unsigned long long)nonce, event_id, current_difficulty); - - // Check if we've reached target difficulty - if (current_difficulty >= target_difficulty) { - printf(" āœ“ SUCCESS!\n\n"); - - // Print final successful event - printf("=== SUCCESSFUL EVENT ===\n"); - char* final_json = cJSON_Print(event); - if (final_json) { - printf("%s\n", final_json); - free(final_json); - } - - printf("\nšŸŽ‰ Mining completed!\n"); - printf(" Attempts: %d\n", attempt + 1); - printf(" Final nonce: %llu\n", (unsigned long long)nonce); - printf(" Final difficulty: %d (target was %d)\n", current_difficulty, target_difficulty); - - cJSON_Delete(event); - nostr_cleanup(); - return 0; - } else { - printf(" (need %d)\n", target_difficulty); - } - - cJSON_Delete(event); - nonce++; - } - - // If we reach here, we've exceeded max attempts - printf("\nāŒ Mining failed after %d attempts\n", max_attempts); - printf("Consider increasing max_attempts or reducing target_difficulty\n"); - - nostr_cleanup(); - return 1; -}