/* * 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; }