From 4c66eda10eb055b4a10d4bea60682f21f71f3789 Mon Sep 17 00:00:00 2001 From: Silberengel Date: Fri, 3 Oct 2025 17:01:34 +0200 Subject: [PATCH] implement bootstrap relays --- app/config/config.go | 1 + docker-compose.yml | 3 +++ pkg/acl/follows.go | 30 ++++++++++++++++++++++++++++-- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/app/config/config.go b/app/config/config.go index f942ae8..729f972 100644 --- a/app/config/config.go +++ b/app/config/config.go @@ -42,6 +42,7 @@ type C struct { ACLMode string `env:"ORLY_ACL_MODE" usage:"ACL mode: follows,none" default:"none"` SpiderMode string `env:"ORLY_SPIDER_MODE" usage:"spider mode: none,follows" default:"none"` SpiderFrequency time.Duration `env:"ORLY_SPIDER_FREQUENCY" usage:"spider frequency in seconds" default:"1h"` + BootstrapRelays []string `env:"ORLY_BOOTSTRAP_RELAYS" usage:"comma-separated list of bootstrap relay URLs for initial sync"` NWCUri string `env:"ORLY_NWC_URI" usage:"NWC (Nostr Wallet Connect) connection string for Lightning payments"` SubscriptionEnabled bool `env:"ORLY_SUBSCRIPTION_ENABLED" default:"false" usage:"enable subscription-based access control requiring payment for non-directory events"` MonthlyPriceSats int64 `env:"ORLY_MONTHLY_PRICE_SATS" default:"6000" usage:"price in satoshis for one month subscription (default ~$2 USD)"` diff --git a/docker-compose.yml b/docker-compose.yml index 482a247..6abc2c2 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -28,6 +28,9 @@ services: - ORLY_ACL_MODE=follows - ORLY_SPIDER_MODE=follows + # Bootstrap relay URLs for initial sync + - ORLY_BOOTSTRAP_RELAYS=wss://profiles.nostr1.com,wss://purplepag.es,wss://relay.damus.io,wss://nostr.wine,wss://relay.nostr.band,wss://freelay.sovbit.host + # Subscription Settings (optional) - ORLY_SUBSCRIPTION_ENABLED=false - ORLY_MONTHLY_PRICE_SATS=0 diff --git a/pkg/acl/follows.go b/pkg/acl/follows.go index 0d6abb4..de22486 100644 --- a/pkg/acl/follows.go +++ b/pkg/acl/follows.go @@ -158,6 +158,8 @@ func (f *Follows) adminRelays() (urls []string) { copy(admins, f.admins) f.followsMx.RUnlock() seen := make(map[string]struct{}) + + // First, try to get relay URLs from admin kind 10002 events for _, adm := range admins { fl := &filter.F{ Authors: tag.NewFromAny(adm), @@ -194,6 +196,29 @@ func (f *Follows) adminRelays() (urls []string) { } } } + + // If no admin relays found, use bootstrap relays as fallback + if len(urls) == 0 { + log.I.F("no admin relays found in DB, checking bootstrap relays") + if len(f.cfg.BootstrapRelays) > 0 { + log.I.F("using bootstrap relays: %v", f.cfg.BootstrapRelays) + for _, relay := range f.cfg.BootstrapRelays { + n := string(normalize.URL(relay)) + if n == "" { + log.W.F("invalid bootstrap relay URL: %s", relay) + continue + } + if _, ok := seen[n]; ok { + continue + } + seen[n] = struct{}{} + urls = append(urls, n) + } + } else { + log.W.F("no bootstrap relays configured") + } + } + return } @@ -211,7 +236,7 @@ func (f *Follows) startSubscriptions(ctx context.Context) { urls := f.adminRelays() log.I.S(urls) if len(urls) == 0 { - log.W.F("follows syncer: no admin relays found in DB (kind 10002)") + log.W.F("follows syncer: no admin relays found in DB (kind 10002) and no bootstrap relays configured") return } log.T.F( @@ -256,6 +281,7 @@ func (f *Follows) startSubscriptions(ctx context.Context) { ff := &filter.S{} f1 := &filter.F{ Authors: tag.NewFromBytesSlice(authors...), + Kinds: kind.NewS(kind.New(kind.RelayListMetadata.K)), Limit: values.ToUintPointer(0), } *ff = append(*ff, f1) @@ -365,7 +391,7 @@ func (f *Follows) Syncer() { func (f *Follows) GetFollowedPubkeys() [][]byte { f.followsMx.RLock() defer f.followsMx.RUnlock() - + followedPubkeys := make([][]byte, len(f.follows)) copy(followedPubkeys, f.follows) return followedPubkeys