upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src/http/nip11.rs
diff options
context:
space:
mode:
authorDanConwayDev <DanConwayDev@protonmail.com>2026-01-09 07:57:54 +0000
committerDanConwayDev <DanConwayDev@protonmail.com>2026-01-09 07:57:54 +0000
commit7cc5d37cbf4f02f0bb7eee6342dc1ede5a841a7b (patch)
tree62d3dcf291a7ca67d18cf397b448fb98d62553ba /src/http/nip11.rs
parent6bc2d70f6dd351521e522cc4d0f1ac188848ad26 (diff)
feat: replace owner-npub with relay-owner-nsec for persistent operator identity
Replace the owner-npub configuration option with relay-owner-nsec to provide a persistent cryptographic identity for the relay operator. This addresses NIP-42 authentication requirements discovered during sync debugging. Motivation: - Some relays (e.g., relay.damus.io) require NIP-42 authentication for advanced features like NIP-77 negentropy sync - Previously used random ephemeral keys per connection, providing no persistent identity - Other relays can now recognize us by pubkey for reputation-based rate limiting - Ensures consistency between NIP-11 pubkey and authentication key Changes: - Config: relay_owner_nsec with auto-load/generate from .relay-owner.nsec - NIP-11: Pubkey derived from nsec instead of separate npub field - Sync: RelayConnection now uses operator keys for NIP-42 auth - Docs: Updated README, .env.example, and added .relay-owner.nsec to gitignore Key Features: - Auto-generates key on first run and saves to .relay-owner.nsec - Loads existing key from file on subsequent runs - Can override via CLI flag or environment variable - Enables reputation building across relay network - Future-ready for event signing and WoT calculations Testing: - 225/232 tests passing (7 pre-existing purgatory failures unrelated) - Verified key generation, loading, and NIP-11 derivation - Release build successful Related: work/sync-debug-analysis.md, work/relay-owner-nsec-implementation.md
Diffstat (limited to 'src/http/nip11.rs')
-rw-r--r--src/http/nip11.rs53
1 files changed, 15 insertions, 38 deletions
diff --git a/src/http/nip11.rs b/src/http/nip11.rs
index 7df8306..cf31cf3 100644
--- a/src/http/nip11.rs
+++ b/src/http/nip11.rs
@@ -59,7 +59,7 @@ impl RelayInformationDocument {
59 Self { 59 Self {
60 name: config.relay_name(), 60 name: config.relay_name(),
61 description: config.relay_description.clone(), 61 description: config.relay_description.clone(),
62 pubkey: config.owner_npub.clone(), 62 pubkey: config.relay_owner_npub().ok(),
63 contact: None, // Could be added to config if needed 63 contact: None, // Could be added to config if needed
64 supported_nips: vec![ 64 supported_nips: vec![
65 1, // NIP-01: Basic protocol flow 65 1, // NIP-01: Basic protocol flow
@@ -93,30 +93,21 @@ mod tests {
93 93
94 #[test] 94 #[test]
95 fn test_relay_information_document_structure() { 95 fn test_relay_information_document_structure() {
96 let config = Config { 96 let mut config = Config::for_testing();
97 domain: "relay.example.com".to_string(), 97 config.domain = "relay.example.com".to_string();
98 owner_npub: Some("npub1test".to_string()), 98 config.relay_name_override = Some("Test Relay".to_string());
99 relay_name_override: Some("Test Relay".to_string()), 99 config.relay_description = "A test relay".to_string();
100 relay_description: "A test relay".to_string(),
101 git_data_path: "./data/git".to_string(),
102 relay_data_path: "./data/relay".to_string(),
103 bind_address: "127.0.0.1:8080".to_string(),
104 database_backend: crate::config::DatabaseBackend::Memory,
105 metrics_enabled: true,
106 metrics_connection_per_ip_abuse_threshold: 10,
107 metrics_top_n_repos: 10,
108 sync_bootstrap_relay_url: None,
109 sync_max_backoff_secs: 3600,
110 sync_disconnect_check_interval_secs: 60,
111 sync_base_backoff_secs: 5,
112 sync_disable_negentropy: false,
113 };
114 100
115 let doc = RelayInformationDocument::from_config(&config); 101 let doc = RelayInformationDocument::from_config(&config);
116 102
117 assert_eq!(doc.name, "Test Relay"); 103 assert_eq!(doc.name, "Test Relay");
118 assert_eq!(doc.description, "A test relay"); 104 assert_eq!(doc.description, "A test relay");
119 assert_eq!(doc.pubkey, Some("npub1test".to_string())); 105
106 // Verify pubkey is present and is a valid npub
107 assert!(doc.pubkey.is_some());
108 let pubkey = doc.pubkey.unwrap();
109 assert!(pubkey.starts_with("npub1"));
110
120 assert!(doc.supported_nips.contains(&1)); 111 assert!(doc.supported_nips.contains(&1));
121 assert!(doc.supported_nips.contains(&11)); 112 assert!(doc.supported_nips.contains(&11));
122 assert!(doc.supported_nips.contains(&34)); 113 assert!(doc.supported_nips.contains(&34));
@@ -132,24 +123,10 @@ mod tests {
132 123
133 #[test] 124 #[test]
134 fn test_relay_information_document_json() { 125 fn test_relay_information_document_json() {
135 let config = Config { 126 let mut config = Config::for_testing();
136 domain: "relay.example.com".to_string(), 127 config.domain = "relay.example.com".to_string();
137 owner_npub: Some("npub1test".to_string()), 128 config.relay_name_override = Some("Test Relay".to_string());
138 relay_name_override: Some("Test Relay".to_string()), 129 config.relay_description = "A test relay".to_string();
139 relay_description: "A test relay".to_string(),
140 git_data_path: "./data/git".to_string(),
141 relay_data_path: "./data/relay".to_string(),
142 bind_address: "127.0.0.1:8080".to_string(),
143 database_backend: crate::config::DatabaseBackend::Memory,
144 metrics_enabled: true,
145 metrics_connection_per_ip_abuse_threshold: 10,
146 metrics_top_n_repos: 10,
147 sync_bootstrap_relay_url: None,
148 sync_max_backoff_secs: 3600,
149 sync_disconnect_check_interval_secs: 60,
150 sync_base_backoff_secs: 5,
151 sync_disable_negentropy: false,
152 };
153 130
154 let doc = RelayInformationDocument::from_config(&config); 131 let doc = RelayInformationDocument::from_config(&config);
155 let json = doc.to_json().expect("Failed to serialize to JSON"); 132 let json = doc.to_json().expect("Failed to serialize to JSON");