v0.4.1 - Fixed startup bug

This commit is contained in:
Your Name
2025-10-01 17:23:50 -04:00
parent 524f9bd84f
commit c3bab033ed
7 changed files with 174 additions and 594 deletions

View File

@@ -917,10 +917,11 @@ cJSON* create_default_config_event(const unsigned char* admin_privkey_bytes,
int first_time_startup_sequence(const cli_options_t* cli_options) {
log_info("Starting first-time startup sequence...");
// 1. Generate or use provided admin keypair
unsigned char admin_privkey_bytes[32];
char admin_privkey[65], admin_pubkey[65];
int generated_admin_key = 0; // Track if we generated a new admin key
if (cli_options && strlen(cli_options->admin_pubkey_override) == 64) {
// Use provided admin public key directly - skip private key generation entirely
@@ -943,6 +944,7 @@ int first_time_startup_sequence(const cli_options_t* cli_options) {
// Set a dummy private key that will never be used (not displayed or stored)
memset(admin_privkey_bytes, 0, 32); // Zero out for security
memset(admin_privkey, 0, sizeof(admin_privkey)); // Zero out the hex string
generated_admin_key = 0; // Did not generate a new key
} else {
// Generate random admin keypair using /dev/urandom + nostr_core_lib
log_info("Generating random admin keypair");
@@ -959,6 +961,7 @@ int first_time_startup_sequence(const cli_options_t* cli_options) {
return -1;
}
nostr_bytes_to_hex(admin_pubkey_bytes, 32, admin_pubkey);
generated_admin_key = 1; // Generated a new key
}
// 2. Generate or use provided relay keypair
@@ -1017,57 +1020,40 @@ int first_time_startup_sequence(const cli_options_t* cli_options) {
g_temp_relay_privkey[sizeof(g_temp_relay_privkey) - 1] = '\0';
log_info("Relay private key cached for secure storage after database initialization");
// 6. Handle configuration setup based on admin key availability
if (cli_options && strlen(cli_options->admin_pubkey_override) == 64) {
// Admin pubkey provided - will populate config table after database initialization
log_info("Admin pubkey provided - config table will be populated after database initialization");
// 6. Handle configuration setup - defaults will be populated after database initialization
log_info("Configuration setup prepared - defaults will be populated after database initialization");
// CLI overrides will be applied after database initialization in main.c
// This prevents "g_db is NULL" errors during first-time startup
// 10. Print admin private key for user to save (only if we generated a new key)
if (generated_admin_key) {
printf("\n");
printf("=================================================================\n");
printf("IMPORTANT: SAVE THIS ADMIN PRIVATE KEY SECURELY!\n");
printf("=================================================================\n");
printf("Admin Private Key: %s\n", admin_privkey);
printf("Admin Public Key: %s\n", admin_pubkey);
printf("Relay Public Key: %s\n", relay_pubkey);
printf("\nDatabase: %s\n", g_database_path);
printf("\nThis admin private key is needed to update configuration!\n");
printf("Store it safely - it will not be displayed again.\n");
printf("=================================================================\n");
printf("\n");
} else {
// Admin private key available - create signed configuration event
log_info("Admin private key available - creating signed configuration event");
// Create initial configuration event using defaults
cJSON* config_event = create_default_config_event(admin_privkey_bytes, relay_privkey, relay_pubkey, cli_options);
if (!config_event) {
log_error("Failed to create default configuration event");
return -1;
}
// Process configuration through admin API instead of storing in events table
if (process_startup_config_event_with_fallback(config_event) == 0) {
log_success("Initial configuration processed successfully through admin API");
} else {
log_warning("Failed to process initial configuration - will retry after database init");
// Cache the event for later processing
if (g_pending_config_event) {
cJSON_Delete(g_pending_config_event);
}
g_pending_config_event = cJSON_Duplicate(config_event, 1);
}
// Cache the current config
if (g_current_config) {
cJSON_Delete(g_current_config);
}
g_current_config = cJSON_Duplicate(config_event, 1);
// Clean up
cJSON_Delete(config_event);
printf("\n");
printf("=================================================================\n");
printf("RELAY STARTUP COMPLETE\n");
printf("=================================================================\n");
printf("Using provided admin public key for authentication\n");
printf("Admin Public Key: %s\n", admin_pubkey);
printf("Relay Public Key: %s\n", relay_pubkey);
printf("\nDatabase: %s\n", g_database_path);
printf("=================================================================\n");
printf("\n");
}
// 10. Print admin private key for user to save
printf("\n");
printf("=================================================================\n");
printf("IMPORTANT: SAVE THIS ADMIN PRIVATE KEY SECURELY!\n");
printf("=================================================================\n");
printf("Admin Private Key: %s\n", admin_privkey);
printf("Admin Public Key: %s\n", admin_pubkey);
printf("Relay Public Key: %s\n", relay_pubkey);
printf("\nDatabase: %s\n", g_database_path);
printf("\nThis admin private key is needed to update configuration!\n");
printf("Store it safely - it will not be displayed again.\n");
printf("=================================================================\n");
printf("\n");
log_success("First-time startup sequence completed");
return 0;
}

View File

@@ -348,18 +348,18 @@ int init_database(const char* database_path_override) {
}
if (!has_auth_rules) {
// Add auth_rules table
// Add auth_rules table matching sql_schema.h
const char* create_auth_rules_sql =
"CREATE TABLE IF NOT EXISTS auth_rules ("
" id INTEGER PRIMARY KEY AUTOINCREMENT,"
" rule_type TEXT NOT NULL," // 'pubkey_whitelist', 'pubkey_blacklist', 'hash_blacklist'
" operation TEXT NOT NULL," // 'event', 'event_kind_1', etc.
" rule_target TEXT NOT NULL," // pubkey, hash, or other identifier
" enabled INTEGER DEFAULT 1," // 0 = disabled, 1 = enabled
" priority INTEGER DEFAULT 1000," // Lower numbers = higher priority
" description TEXT," // Optional description
" created_at INTEGER DEFAULT (strftime('%s', 'now')),"
" UNIQUE(rule_type, operation, rule_target)"
" rule_type TEXT NOT NULL CHECK (rule_type IN ('whitelist', 'blacklist', 'rate_limit', 'auth_required')),"
" pattern_type TEXT NOT NULL CHECK (pattern_type IN ('pubkey', 'kind', 'ip', 'global')),"
" pattern_value TEXT,"
" action TEXT NOT NULL CHECK (action IN ('allow', 'deny', 'require_auth', 'rate_limit')),"
" parameters TEXT,"
" active INTEGER NOT NULL DEFAULT 1,"
" created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),"
" updated_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now'))"
");";
char* error_msg = NULL;
@@ -373,6 +373,24 @@ int init_database(const char* database_path_override) {
return -1;
}
log_success("Created auth_rules table");
// Add indexes for auth_rules table
const char* create_auth_rules_indexes_sql =
"CREATE INDEX IF NOT EXISTS idx_auth_rules_pattern ON auth_rules(pattern_type, pattern_value);"
"CREATE INDEX IF NOT EXISTS idx_auth_rules_type ON auth_rules(rule_type);"
"CREATE INDEX IF NOT EXISTS idx_auth_rules_active ON auth_rules(active);";
char* index_error_msg = NULL;
int index_rc = sqlite3_exec(g_db, create_auth_rules_indexes_sql, NULL, NULL, &index_error_msg);
if (index_rc != SQLITE_OK) {
char index_error_log[512];
snprintf(index_error_log, sizeof(index_error_log), "Failed to create auth_rules indexes: %s",
index_error_msg ? index_error_msg : "unknown error");
log_error(index_error_log);
if (index_error_msg) sqlite3_free(index_error_msg);
return -1;
}
log_success("Created auth_rules indexes");
} else {
log_info("auth_rules table already exists, skipping creation");
}
@@ -1408,35 +1426,43 @@ int main(int argc, char* argv[]) {
}
// Handle configuration setup after database is initialized
if (cli_options.admin_pubkey_override && strlen(cli_options.admin_pubkey_override) == 64) {
// Admin pubkey provided - populate config table directly
log_info("Populating config table for admin pubkey override after database initialization");
// Always populate defaults directly in config table (abandoning legacy event signing)
log_info("Populating config table with defaults after database initialization");
// Populate default config values in table
if (populate_default_config_values() != 0) {
log_error("Failed to populate default config values");
cleanup_configuration_system();
nostr_cleanup();
close_database();
return 1;
}
// Add pubkeys to config table
if (add_pubkeys_to_config_table() != 0) {
log_error("Failed to add pubkeys to config table");
cleanup_configuration_system();
nostr_cleanup();
close_database();
return 1;
}
log_success("Configuration populated directly in config table after database initialization");
} else {
// Admin private key available - retry storing initial config event
if (retry_store_initial_config_event() != 0) {
log_warning("Failed to store initial config event - will retry later");
}
// Populate default config values in table
if (populate_default_config_values() != 0) {
log_error("Failed to populate default config values");
cleanup_configuration_system();
nostr_cleanup();
close_database();
return 1;
}
// Apply CLI overrides now that database is available
if (cli_options.port_override > 0) {
char port_str[16];
snprintf(port_str, sizeof(port_str), "%d", cli_options.port_override);
if (update_config_in_table("relay_port", port_str) != 0) {
log_error("Failed to update relay port override in config table");
cleanup_configuration_system();
nostr_cleanup();
close_database();
return 1;
}
log_info("Applied port override from command line");
printf(" Port: %d (overriding default)\n", cli_options.port_override);
}
// Add pubkeys to config table
if (add_pubkeys_to_config_table() != 0) {
log_error("Failed to add pubkeys to config table");
cleanup_configuration_system();
nostr_cleanup();
close_database();
return 1;
}
log_success("Configuration populated directly in config table after database initialization");
// Now store the pubkeys in config table since database is available
const char* admin_pubkey = get_admin_pubkey_cached();
@@ -1539,6 +1565,21 @@ int main(int argc, char* argv[]) {
log_warning("No configuration event found in existing database");
}
// Apply CLI overrides for existing relay (port override should work even for existing relays)
if (cli_options.port_override > 0) {
char port_str[16];
snprintf(port_str, sizeof(port_str), "%d", cli_options.port_override);
if (update_config_in_table("relay_port", port_str) != 0) {
log_error("Failed to update relay port override in config table for existing relay");
cleanup_configuration_system();
nostr_cleanup();
close_database();
return 1;
}
log_info("Applied port override from command line for existing relay");
printf(" Port: %d (overriding configured port)\n", cli_options.port_override);
}
// Free memory
free(relay_pubkey);
for (int i = 0; existing_files[i]; i++) {