Improved POW
This commit is contained in:
parent
3d2537603c
commit
c569c0c346
42
Makefile
42
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)
|
||||
|
|
96
build.sh
96
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)
|
||||
|
|
BIN
libnostr_core.a
BIN
libnostr_core.a
Binary file not shown.
|
@ -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
|
||||
|
|
Binary file not shown.
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#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", "<nonce>", "<target_difficulty>"]
|
||||
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;
|
||||
}
|
Loading…
Reference in New Issue