upleb.uk

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

summaryrefslogtreecommitdiff
path: root/src/nostr/builder.rs
blob: cd1f4d260a64abc099b19f3218f11c34ddd65de7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/// Nostr Relay Builder Configuration
///
/// This module integrates nostr-relay-builder with NIP-34 validation logic
/// preserved from the original implementation.
use std::net::SocketAddr;
use std::path::Path;

use nostr::nips::nip19::ToBech32;
use nostr_relay_builder::prelude::*;

use crate::config::Config;
use crate::nostr::events::{
    validate_announcement, validate_state, KIND_REPOSITORY_ANNOUNCEMENT, KIND_REPOSITORY_STATE,
};

/// NIP-34 Write Policy
///
/// Validates repository announcement and state events according to GRASP-01 spec.
/// Preserves all original validation logic from src/nostr/events.rs.
#[derive(Debug, Clone)]
pub struct Nip34WritePolicy {
    domain: String,
}

impl Nip34WritePolicy {
    pub fn new(domain: impl Into<String>) -> Self {
        Self {
            domain: domain.into(),
        }
    }
}

impl WritePolicy for Nip34WritePolicy {
    fn admit_event<'a>(
        &'a self,
        event: &'a nostr_relay_builder::prelude::Event,
        _addr: &'a SocketAddr,
    ) -> BoxedFuture<'a, PolicyResult> {
        Box::pin(async move {
            match event.kind.as_u16() {
                KIND_REPOSITORY_ANNOUNCEMENT => match validate_announcement(event, &self.domain) {
                    Ok(_) => {
                        tracing::debug!(
                            "Accepted repository announcement: {}",
                            event
                                .id
                                .to_bech32()
                                .unwrap_or_else(|_| "invalid".to_string())
                        );
                        PolicyResult::Accept
                    }
                    Err(e) => {
                        tracing::warn!(
                            "Rejected repository announcement {}: {}",
                            event
                                .id
                                .to_bech32()
                                .unwrap_or_else(|_| "invalid".to_string()),
                            e
                        );
                        PolicyResult::Reject(e.to_string())
                    }
                },
                KIND_REPOSITORY_STATE => match validate_state(event) {
                    Ok(_) => {
                        tracing::debug!(
                            "Accepted repository state: {}",
                            event
                                .id
                                .to_bech32()
                                .unwrap_or_else(|_| "invalid".to_string())
                        );
                        PolicyResult::Accept
                    }
                    Err(e) => {
                        tracing::warn!(
                            "Rejected repository state {}: {}",
                            event
                                .id
                                .to_bech32()
                                .unwrap_or_else(|_| "invalid".to_string()),
                            e
                        );
                        PolicyResult::Reject(e.to_string())
                    }
                },
                // Accept all other event kinds without validation
                _ => PolicyResult::Accept,
            }
        })
    }
}

/// Create a configured LocalRelay with NIP-34 validation
pub fn create_relay(config: &Config) -> Result<LocalRelay> {
    tracing::info!("Configuring nostr relay...");

    // Determine database path
    let db_path = Path::new(&config.relay_data_path);

    // Create database - using in-memory for now, can switch to persistent later
    // TODO: Add configuration for NostrDB or LMDB backends
    let database = MemoryDatabase::with_opts(MemoryDatabaseOptions {
        events: true,
        max_events: Some(100_000),
    });

    tracing::info!("Using in-memory database (path: {})", db_path.display());

    // Build relay with NIP-34 validation
    let builder = RelayBuilder::default()
        .database(database)
        .write_policy(Nip34WritePolicy::new(&config.domain));

    tracing::info!(
        "Relay configured with NIP-34 validation for domain: {}",
        config.domain
    );

    Ok(LocalRelay::new(builder))
}