database

package
v0.32.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 3, 2025 License: Unlicense Imports: 42 Imported by: 0

Documentation

Overview

Package database provides filter utilities for normalizing tag values.

The nostr library optimizes e/p tag values by storing them in binary format (32 bytes + null terminator) rather than hex strings (64 chars). However, filter tags from client queries come as hex strings and don't go through the same binary encoding during unmarshalling.

This file provides utilities to normalize filter tags to match the binary encoding used in stored events, ensuring consistent index lookups and tag comparisons.

Package database provides shared import utilities for events

Index

Constants

View Source
const (
	// BinaryEncodedLen is the length of a binary-encoded 32-byte hash with null terminator
	BinaryEncodedLen = 33
	// HexEncodedLen is the length of a hex-encoded 32-byte hash
	HexEncodedLen = 64
	// HashLen is the raw length of a hash (pubkey/event ID)
	HashLen = 32
)

Tag binary encoding constants (matching the nostr library)

Variables

View Source
var (
	// ErrOlderThanExisting is returned when a candidate event is older than an existing replaceable/addressable event.
	ErrOlderThanExisting = errors.New("older than existing event")
	// ErrMissingDTag is returned when a parameterized replaceable event lacks the required 'd' tag.
	ErrMissingDTag = errors.New("event is missing a d tag identifier")
)

Functions

func BinaryToHex added in v0.30.3

func BinaryToHex(binVal []byte) []byte

BinaryToHex converts a 33-byte binary value to 64-character hex string Returns nil if the input is not in binary format

func CanUsePTagGraph added in v0.29.11

func CanUsePTagGraph(f *filter.F) bool

CanUsePTagGraph determines if a filter can benefit from p-tag graph optimization.

Requirements: - Filter must have #p tags - Filter should NOT have authors (different index is better for that case) - Optimization works best with kinds filter but is optional

func CheckExpiration

func CheckExpiration(ev *event.E) (expired bool)

func CreateIdHashFromData

func CreateIdHashFromData(data []byte) (i *types2.IdHash, err error)

CreateIdHashFromData creates an IdHash from data that could be hex or binary

func CreatePubHashFromData

func CreatePubHashFromData(data []byte) (p *types2.PubHash, err error)

CreatePubHashFromData creates a PubHash from data that could be hex or binary

func GetIndexesForEvent

func GetIndexesForEvent(ev *event.E, serial uint64) (
	idxs [][]byte, err error,
)

GetIndexesForEvent creates all the indexes for an event.E instance as defined in keys.go. It returns a slice of byte slices that can be used to store the event in the database.

func HexToBinary added in v0.30.3

func HexToBinary(hexVal []byte) []byte

HexToBinary converts a 64-character hex string to 33-byte binary format Returns nil if the input is not a valid hex string

func IsBinaryEncoded added in v0.30.3

func IsBinaryEncoded(val []byte) bool

IsBinaryEncoded checks if a value field is stored in optimized binary format

func IsBinaryOptimizedTag added in v0.30.3

func IsBinaryOptimizedTag(key byte) bool

IsBinaryOptimizedTag returns true if the given tag key uses binary encoding

func IsHexString

func IsHexString(data []byte) (isHex bool)

IsHexString checks if the byte slice contains only hex characters

func IsValidHexValue added in v0.30.3

func IsValidHexValue(b []byte) bool

IsValidHexValue checks if a byte slice is a valid 64-character hex string

func NewLogger

func NewLogger(logLevel int, label string) (l *logger)

NewLogger creates a new badger logger.

func NormalizeFilter added in v0.30.3

func NormalizeFilter(f *filter.F) *filter.F

NormalizeFilter normalizes a filter's tags for consistent database queries. This should be called before using a filter for database lookups. The original filter is not modified; a copy with normalized tags is returned.

func NormalizeFilterTag added in v0.30.3

func NormalizeFilterTag(t *tag.T) *tag.T

NormalizeFilterTag creates a new tag with binary-encoded values for e/p tags. The original tag is not modified.

func NormalizeFilterTags added in v0.30.3

func NormalizeFilterTags(tags *tag.S) *tag.S

NormalizeFilterTags normalizes all tags in a tag.S, converting e/p hex values to binary. Returns a new tag.S with normalized tags.

func NormalizeTagToHex added in v0.30.3

func NormalizeTagToHex(val []byte) []byte

NormalizeTagToHex returns the hex representation of a tag value. For binary-encoded values, converts to hex. For hex values, returns as-is.

func NormalizeTagValue added in v0.30.3

func NormalizeTagValue(key byte, val []byte) []byte

NormalizeTagValue normalizes a tag value for the given key. For e/p tags, hex values are converted to binary format. Other tags are returned unchanged.

func NormalizeTagValueForHash added in v0.30.3

func NormalizeTagValueForHash(key byte, valueBytes []byte) []byte

NormalizeTagValueForHash normalizes a tag value for consistent hashing. For 'e' and 'p' tags, the nostr library stores values in binary format (32 bytes), but filters from clients come with hex strings (64 chars). This function ensures that filter values are converted to binary to match the stored index format.

This function delegates to NormalizeTagValue from filter_utils.go for consistency.

func RegisterDgraphFactory added in v0.29.1

func RegisterDgraphFactory(factory func(context.Context, context.CancelFunc, *DatabaseConfig) (Database, error))

RegisterDgraphFactory registers the dgraph database factory This is called from the dgraph package's init() function

func RegisterNeo4jFactory added in v0.29.3

func RegisterNeo4jFactory(factory func(context.Context, context.CancelFunc, *DatabaseConfig) (Database, error))

RegisterNeo4jFactory registers the neo4j database factory This is called from the neo4j package's init() function

func RegisterWasmDBFactory added in v0.32.0

func RegisterWasmDBFactory(factory func(context.Context, context.CancelFunc, *DatabaseConfig) (Database, error))

RegisterWasmDBFactory registers the wasmdb database factory This is called from the wasmdb package's init() function

func TagValuesMatch added in v0.30.3

func TagValuesMatch(key byte, eventVal, filterVal []byte) bool

TagValuesMatch compares two tag values, handling both binary and hex encodings. This is useful for post-query tag matching where event values may be binary and filter values may be hex (or vice versa).

func TagValuesMatchUsingTagMethods added in v0.30.3

func TagValuesMatchUsingTagMethods(eventTag *tag.T, filterVal []byte) bool

TagValuesMatchUsingTagMethods compares an event tag's value with a filter value using the tag.T methods. This leverages the nostr library's ValueHex() method for proper binary/hex conversion.

func TokenHashes added in v0.9.0

func TokenHashes(content []byte) [][]byte

TokenHashes extracts unique word hashes (8-byte truncated sha256) from content. Rules: - Unicode-aware: words are sequences of letters or numbers. - Lowercased using unicode case mapping. - Ignore URLs (starting with http://, https://, www., or containing "://"). - Ignore nostr: URIs and #[n] mentions. - Ignore words shorter than 2 runes. - Exclude 64-character hexadecimal strings (likely IDs/pubkeys).

Types

type AllowedEvent added in v0.17.0

type AllowedEvent struct {
	ID     string    `json:"id"`
	Reason string    `json:"reason,omitempty"`
	Added  time.Time `json:"added"`
}

AllowedEvent represents an allowed event entry

type AllowedKind added in v0.17.0

type AllowedKind struct {
	Kind  int       `json:"kind"`
	Added time.Time `json:"added"`
}

AllowedKind represents an allowed event kind

type AllowedPubkey added in v0.17.0

type AllowedPubkey struct {
	Pubkey string    `json:"pubkey"`
	Reason string    `json:"reason,omitempty"`
	Added  time.Time `json:"added"`
}

AllowedPubkey represents an allowed public key entry

type BannedEvent added in v0.17.0

type BannedEvent struct {
	ID     string    `json:"id"`
	Reason string    `json:"reason,omitempty"`
	Added  time.Time `json:"added"`
}

BannedEvent represents a banned event entry

type BannedPubkey added in v0.17.0

type BannedPubkey struct {
	Pubkey string    `json:"pubkey"`
	Reason string    `json:"reason,omitempty"`
	Added  time.Time `json:"added"`
}

BannedPubkey represents a banned public key entry

type BlockedIP added in v0.17.0

type BlockedIP struct {
	IP     string    `json:"ip"`
	Reason string    `json:"reason,omitempty"`
	Added  time.Time `json:"added"`
}

BlockedIP represents a blocked IP address entry

type D

type D struct {
	Logger *logger

	*badger.DB
	// contains filtered or unexported fields
}

D implements the Database interface using Badger as the storage backend

func New

func New(
	ctx context.Context, cancel context.CancelFunc, dataDir, logLevel string,
) (
	d *D, err error,
)

New creates a new Badger database instance with default configuration. This is provided for backward compatibility with existing callers. For full configuration control, use NewWithConfig instead.

func NewWithConfig added in v0.31.8

func NewWithConfig(
	ctx context.Context, cancel context.CancelFunc, cfg *DatabaseConfig,
) (
	d *D, err error,
)

NewWithConfig creates a new Badger database instance with full configuration. This is the preferred method when you have access to DatabaseConfig.

func (*D) AddNIP43Member added in v0.27.0

func (d *D) AddNIP43Member(pubkey []byte, inviteCode string) error

AddNIP43Member adds a member to the NIP-43 membership list

func (*D) CacheEvents added in v0.29.11

func (d *D) CacheEvents(f *filter.F, events event.S)

CacheEvents stores events for a filter (without subscription ID)

func (*D) CacheMarshaledJSON added in v0.29.1

func (d *D) CacheMarshaledJSON(f *filter.F, marshaledJSON [][]byte)

CacheMarshaledJSON stores marshaled JSON event envelopes for a filter

func (*D) CheckForDeleted

func (d *D) CheckForDeleted(ev *event.E, admins [][]byte) (err error)

CheckForDeleted checks if the event is deleted, and returns an error with prefix "blocked:" if it is. This function also allows designating admin pubkeys that also may delete the event, normally only the author is allowed to delete an event.

func (*D) CleanupEphemeralEvents added in v0.25.3

func (d *D) CleanupEphemeralEvents()

func (*D) CleanupKind3WithoutPTags added in v0.31.1

func (d *D) CleanupKind3WithoutPTags(ctx context.Context) error

CleanupKind3WithoutPTags scans for kind 3 follow list events that have no p tags and deletes them. This cleanup is needed because the directory spider may have saved malformed events that lost their tags during serialization.

func (*D) Close

func (d *D) Close() (err error)

Close releases resources and closes the database.

func (*D) ConvertSmallEventsToInline added in v0.28.0

func (d *D) ConvertSmallEventsToInline()

ConvertSmallEventsToInline migrates small events (<=384 bytes) to inline storage. This is a Reiser4-inspired optimization that stores small event data in the key itself, avoiding a second database lookup and improving query performance. Also handles replaceable and addressable events with specialized storage.

func (*D) CountEvents added in v0.10.0

func (d *D) CountEvents(c context.Context, f *filter.F) (
	count int, approx bool, err error,
)

CountEvents mirrors the initial selection logic of QueryEvents but stops once we have identified candidate event serials (id/pk/ts). It returns the count of those serials. The `approx` flag is always false as requested.

func (*D) DeleteEvent

func (d *D) DeleteEvent(c context.Context, eid []byte) (err error)

DeleteEvent removes an event from the database identified by `eid`. If noTombstone is false or not provided, a tombstone is created for the event.

func (*D) DeleteEventBySerial

func (d *D) DeleteEventBySerial(
	c context.Context, ser *types.Uint40, ev *event.E,
) (err error)

func (*D) DeleteExpired

func (d *D) DeleteExpired()

func (*D) DeleteInviteCode added in v0.27.0

func (d *D) DeleteInviteCode(code string) error

DeleteInviteCode removes an invite code (after use)

func (*D) DeleteMarker added in v0.6.0

func (d *D) DeleteMarker(key string) (err error)

DeleteMarker removes a marker from the database

func (*D) EventIdsBySerial

func (d *D) EventIdsBySerial(start uint64, count int) (
	evs []uint64, err error,
)

func (*D) Export

func (d *D) Export(c context.Context, w io.Writer, pubkeys ...[]byte)

Export the complete database of stored events to an io.Writer in line structured minified JSON.

func (*D) ExtendBlossomSubscription added in v0.23.3

func (d *D) ExtendBlossomSubscription(
	pubkey []byte, level string, storageMB int64, days int,
) error

ExtendBlossomSubscription extends or creates a blossom subscription with service level

func (*D) ExtendSubscription

func (d *D) ExtendSubscription(pubkey []byte, days int) error

func (*D) FetchEventBySerial

func (d *D) FetchEventBySerial(ser *types.Uint40) (ev *event.E, err error)

func (*D) FetchEventsBySerials added in v0.4.9

func (d *D) FetchEventsBySerials(serials []*types.Uint40) (events map[uint64]*event.E, err error)

FetchEventsBySerials fetches multiple events by their serials in a single database transaction. Returns a map of serial uint64 value to event, only including successfully fetched events.

func (*D) GetAllNIP43Members added in v0.27.0

func (d *D) GetAllNIP43Members() ([][]byte, error)

GetAllNIP43Members returns all NIP-43 members

func (*D) GetBlossomStorageQuota added in v0.23.3

func (d *D) GetBlossomStorageQuota(pubkey []byte) (quotaMB int64, err error)

GetBlossomStorageQuota returns the current blossom storage quota in MB for a pubkey

func (*D) GetCachedEvents added in v0.29.11

func (d *D) GetCachedEvents(f *filter.F) (event.S, bool)

GetCachedEvents retrieves cached events for a filter (without subscription ID) Returns nil, false if not found

func (*D) GetCachedJSON added in v0.29.1

func (d *D) GetCachedJSON(f *filter.F) ([][]byte, bool)

GetCachedJSON retrieves cached marshaled JSON for a filter Returns nil, false if not found

func (*D) GetFullIdPubkeyBySerial

func (d *D) GetFullIdPubkeyBySerial(ser *types.Uint40) (
	fidpk *store.IdPkTs, err error,
)

func (*D) GetFullIdPubkeyBySerials

func (d *D) GetFullIdPubkeyBySerials(sers []*types.Uint40) (
	fidpks []*store.IdPkTs, err error,
)

GetFullIdPubkeyBySerials seeks directly to each serial's prefix in the FullIdPubkey index. The input sers slice is expected to be sorted in ascending order, allowing efficient forward-only iteration via a single Badger iterator.

func (*D) GetMarker added in v0.6.0

func (d *D) GetMarker(key string) (value []byte, err error)

GetMarker retrieves an arbitrary marker from the database

func (*D) GetNIP43Membership added in v0.27.0

func (d *D) GetNIP43Membership(pubkey []byte) (*NIP43Membership, error)

GetNIP43Membership retrieves membership details for a pubkey

func (*D) GetOrCreatePubkeySerial added in v0.29.11

func (d *D) GetOrCreatePubkeySerial(pubkey []byte) (ser *types.Uint40, err error)

GetOrCreatePubkeySerial returns the serial for a pubkey, creating one if it doesn't exist. The pubkey parameter should be 32 bytes (schnorr public key). This function is thread-safe and uses transactions to ensure atomicity.

func (*D) GetOrCreateRelayIdentitySecret added in v0.8.0

func (d *D) GetOrCreateRelayIdentitySecret() (skb []byte, err error)

GetOrCreateRelayIdentitySecret retrieves the existing relay identity secret key or creates and stores a new one if none exists.

func (*D) GetPaymentHistory

func (d *D) GetPaymentHistory(pubkey []byte) ([]Payment, error)

func (*D) GetPubkeyBySerial added in v0.29.11

func (d *D) GetPubkeyBySerial(ser *types.Uint40) (pubkey []byte, err error)

GetPubkeyBySerial returns the full 32-byte pubkey for a given serial.

func (*D) GetPubkeySerial added in v0.29.11

func (d *D) GetPubkeySerial(pubkey []byte) (ser *types.Uint40, err error)

GetPubkeySerial returns the serial for a pubkey if it exists. Returns an error if the pubkey doesn't have a serial yet.

func (*D) GetRelayIdentitySecret added in v0.8.0

func (d *D) GetRelayIdentitySecret() (skb []byte, err error)

GetRelayIdentitySecret returns the relay identity secret key bytes if present. If the key is not found, returns (nil, badger.ErrKeyNotFound).

func (*D) GetSerialById

func (d *D) GetSerialById(id []byte) (ser *types.Uint40, err error)

func (*D) GetSerialsByIds added in v0.4.9

func (d *D) GetSerialsByIds(ids *tag.T) (
	serials map[string]*types.Uint40, err error,
)

GetSerialsByIds takes a tag.T containing multiple IDs and returns a map of IDs to their corresponding serial numbers. It directly queries the IdPrefix index for matching IDs, which is more efficient than using GetIndexesFromFilter.

func (*D) GetSerialsByIdsWithFilter added in v0.4.9

func (d *D) GetSerialsByIdsWithFilter(
	ids *tag.T, fn func(ev *event.E, ser *types.Uint40) bool,
) (serials map[string]*types.Uint40, err error)

GetSerialsByIdsWithFilter takes a tag.T containing multiple IDs and returns a map of IDs to their corresponding serial numbers, applying a filter function to each event. The function directly creates ID index prefixes for efficient querying.

func (*D) GetSerialsByRange

func (d *D) GetSerialsByRange(idx Range) (
	sers types.Uint40s, err error,
)

func (*D) GetSerialsFromFilter

func (d *D) GetSerialsFromFilter(f *filter.F) (
	sers types.Uint40s, err error,
)

func (*D) GetSubscription

func (d *D) GetSubscription(pubkey []byte) (*Subscription, error)

func (*D) HasMarker added in v0.6.0

func (d *D) HasMarker(key string) (exists bool)

HasMarker checks if a marker exists in the database

func (*D) Import

func (d *D) Import(rr io.Reader)

Import a collection of events in line structured minified JSON format (JSONL).

func (*D) ImportEventsFromReader added in v0.24.0

func (d *D) ImportEventsFromReader(ctx context.Context, rr io.Reader) error

ImportEventsFromReader imports events from an io.Reader containing JSONL data

func (*D) ImportEventsFromStrings added in v0.24.0

func (d *D) ImportEventsFromStrings(ctx context.Context, eventJSONs []string, policyManager interface {
	CheckPolicy(action string, ev *event.E, pubkey []byte, remote string) (bool, error)
}) error

ImportEventsFromStrings imports events from a slice of JSON strings with policy filtering

func (*D) Init

func (d *D) Init(path string) (err error)

Init initializes the database with the given path.

func (*D) InvalidateQueryCache added in v0.29.1

func (d *D) InvalidateQueryCache()

InvalidateQueryCache clears all entries from the query cache

func (*D) IsFirstTimeUser added in v0.8.0

func (d *D) IsFirstTimeUser(pubkey []byte) (bool, error)

IsFirstTimeUser checks if a user is logging in for the first time and marks them as seen

func (*D) IsNIP43Member added in v0.27.0

func (d *D) IsNIP43Member(pubkey []byte) (isMember bool, err error)

IsNIP43Member checks if a pubkey is a NIP-43 member

func (*D) IsSubscriptionActive

func (d *D) IsSubscriptionActive(pubkey []byte) (bool, error)

func (*D) Path

func (d *D) Path() string

Path returns the path where the database files are stored.

func (*D) ProcessDelete

func (d *D) ProcessDelete(ev *event.E, admins [][]byte) (err error)

func (*D) PublishNIP43MembershipEvent added in v0.27.0

func (d *D) PublishNIP43MembershipEvent(kind int, pubkey []byte) error

PublishNIP43MembershipEvent publishes membership change events

func (*D) QueryAllVersions added in v0.17.4

func (d *D) QueryAllVersions(c context.Context, f *filter.F) (
	evs event.S, err error,
)

QueryAllVersions queries events and returns all versions of replaceable events

func (*D) QueryCacheStats added in v0.29.1

func (d *D) QueryCacheStats() querycache.CacheStats

QueryCacheStats returns statistics about the query cache

func (*D) QueryDeleteEventsByTargetId added in v0.14.0

func (d *D) QueryDeleteEventsByTargetId(c context.Context, targetEventId []byte) (
	evs event.S, err error,
)

QueryDeleteEventsByTargetId queries for delete events that target a specific event ID

func (*D) QueryEvents

func (d *D) QueryEvents(c context.Context, f *filter.F) (
	evs event.S, err error,
)

func (*D) QueryEventsWithOptions added in v0.14.0

func (d *D) QueryEventsWithOptions(c context.Context, f *filter.F, includeDeleteEvents bool, showAllVersions bool) (
	evs event.S, err error,
)

func (*D) QueryForIds

func (d *D) QueryForIds(c context.Context, f *filter.F) (
	idPkTs []*store.IdPkTs, err error,
)

QueryForIds retrieves a list of IdPkTs based on the provided filter. It supports filtering by ranges and tags but disallows filtering by Ids. Results are sorted by timestamp in reverse chronological order by default. When a search query is present, results are ranked by a 50/50 blend of match count (how many distinct search terms matched) and recency. Returns an error if the filter contains Ids or if any operation fails.

func (*D) QueryForSerials

func (d *D) QueryForSerials(c context.Context, f *filter.F) (
	sers types.Uint40s, err error,
)

QueryForSerials takes a filter and returns the serials of events that match, sorted in reverse chronological order.

func (*D) QueryPTagGraph added in v0.29.11

func (d *D) QueryPTagGraph(f *filter.F) (sers types.Uint40s, err error)

QueryPTagGraph uses the pubkey graph index for efficient p-tag queries.

This query path is optimized for filters like:

{"#p": ["<pubkey>"], "kinds": [1, 6, 7]}

Performance benefits: - 41% smaller index keys (16 bytes vs 27 bytes) - No hash collisions (exact serial match) - Kind-indexed in key structure - Direction-aware filtering

func (*D) Ready added in v0.29.1

func (d *D) Ready() <-chan struct{}

Ready returns a channel that closes when the database is ready to serve requests. This allows callers to wait for database warmup to complete.

func (*D) RecordPayment

func (d *D) RecordPayment(
	pubkey []byte, amount int64, invoice, preimage string,
) error

func (*D) ReencodeEventsWithOptimizedTags added in v0.29.15

func (d *D) ReencodeEventsWithOptimizedTags()

ReencodeEventsWithOptimizedTags re-encodes all events to use the new binary tag format that stores e/p tag values as 33-byte binary (32-byte hash + null) instead of 64-byte hex strings. This reduces memory usage by ~48% for these tags.

func (*D) RemoveNIP43Member added in v0.27.0

func (d *D) RemoveNIP43Member(pubkey []byte) error

RemoveNIP43Member removes a member from the NIP-43 membership list

func (*D) RunMigrations

func (d *D) RunMigrations()

func (*D) SaveEvent

func (d *D) SaveEvent(c context.Context, ev *event.E) (
	replaced bool, err error,
)

SaveEvent saves an event to the database, generating all the necessary indexes.

func (*D) SetLogLevel

func (d *D) SetLogLevel(level string)

func (*D) SetMarker added in v0.6.0

func (d *D) SetMarker(key string, value []byte) (err error)

SetMarker stores an arbitrary marker in the database

func (*D) SetRelayIdentitySecret added in v0.8.0

func (d *D) SetRelayIdentitySecret(skb []byte) (err error)

SetRelayIdentitySecret stores the relay identity secret key bytes (expects 32 bytes).

func (*D) StoreInviteCode added in v0.27.0

func (d *D) StoreInviteCode(code string, expiresAt time.Time) error

StoreInviteCode stores an invite code with expiry

func (*D) Sync

func (d *D) Sync() (err error)

Sync flushes the database buffers to disk.

func (*D) UpdateExpirationTags

func (d *D) UpdateExpirationTags()

func (*D) UpdateWordIndexes added in v0.9.0

func (d *D) UpdateWordIndexes()

func (*D) ValidateInviteCode added in v0.27.0

func (d *D) ValidateInviteCode(code string) (valid bool, err error)

ValidateInviteCode checks if an invite code is valid and not expired

func (*D) Wipe

func (d *D) Wipe() (err error)

func (*D) WouldReplaceEvent added in v0.10.5

func (d *D) WouldReplaceEvent(ev *event.E) (bool, types.Uint40s, error)

WouldReplaceEvent checks if the provided event would replace existing events based on Nostr's replaceable or parameterized replaceable semantics. It returns true if the candidate is newer-or-equal than existing events. If an existing event is newer, it returns (false, nil, ErrOlderThanExisting). If no conflicts exist, it returns (false, nil, nil).

type Database added in v0.29.1

type Database interface {
	// Core lifecycle methods
	Path() string
	Init(path string) error
	Sync() error
	Close() error
	Wipe() error
	SetLogLevel(level string)
	Ready() <-chan struct{} // Returns a channel that closes when database is ready to serve requests

	// Event storage and retrieval
	SaveEvent(c context.Context, ev *event.E) (exists bool, err error)
	GetSerialsFromFilter(f *filter.F) (serials types.Uint40s, err error)
	WouldReplaceEvent(ev *event.E) (bool, types.Uint40s, error)

	QueryEvents(c context.Context, f *filter.F) (evs event.S, err error)
	QueryAllVersions(c context.Context, f *filter.F) (evs event.S, err error)
	QueryEventsWithOptions(c context.Context, f *filter.F, includeDeleteEvents bool, showAllVersions bool) (evs event.S, err error)
	QueryDeleteEventsByTargetId(c context.Context, targetEventId []byte) (evs event.S, err error)
	QueryForSerials(c context.Context, f *filter.F) (serials types.Uint40s, err error)
	QueryForIds(c context.Context, f *filter.F) (idPkTs []*store.IdPkTs, err error)

	CountEvents(c context.Context, f *filter.F) (count int, approximate bool, err error)

	FetchEventBySerial(ser *types.Uint40) (ev *event.E, err error)
	FetchEventsBySerials(serials []*types.Uint40) (events map[uint64]*event.E, err error)

	GetSerialById(id []byte) (ser *types.Uint40, err error)
	GetSerialsByIds(ids *tag.T) (serials map[string]*types.Uint40, err error)
	GetSerialsByIdsWithFilter(ids *tag.T, fn func(ev *event.E, ser *types.Uint40) bool) (serials map[string]*types.Uint40, err error)
	GetSerialsByRange(idx Range) (serials types.Uint40s, err error)

	GetFullIdPubkeyBySerial(ser *types.Uint40) (fidpk *store.IdPkTs, err error)
	GetFullIdPubkeyBySerials(sers []*types.Uint40) (fidpks []*store.IdPkTs, err error)

	// Event deletion
	DeleteEvent(c context.Context, eid []byte) error
	DeleteEventBySerial(c context.Context, ser *types.Uint40, ev *event.E) error
	DeleteExpired()
	ProcessDelete(ev *event.E, admins [][]byte) error
	CheckForDeleted(ev *event.E, admins [][]byte) error

	// Import/Export
	Import(rr io.Reader)
	Export(c context.Context, w io.Writer, pubkeys ...[]byte)
	ImportEventsFromReader(ctx context.Context, rr io.Reader) error
	ImportEventsFromStrings(ctx context.Context, eventJSONs []string, policyManager interface {
		CheckPolicy(action string, ev *event.E, pubkey []byte, remote string) (bool, error)
	}) error

	// Relay identity
	GetRelayIdentitySecret() (skb []byte, err error)
	SetRelayIdentitySecret(skb []byte) error
	GetOrCreateRelayIdentitySecret() (skb []byte, err error)

	// Markers (metadata key-value storage)
	SetMarker(key string, value []byte) error
	GetMarker(key string) (value []byte, err error)
	HasMarker(key string) bool
	DeleteMarker(key string) error

	// Subscriptions (payment-based access control)
	GetSubscription(pubkey []byte) (*Subscription, error)
	IsSubscriptionActive(pubkey []byte) (bool, error)
	ExtendSubscription(pubkey []byte, days int) error
	RecordPayment(pubkey []byte, amount int64, invoice, preimage string) error
	GetPaymentHistory(pubkey []byte) ([]Payment, error)
	ExtendBlossomSubscription(pubkey []byte, tier string, storageMB int64, daysExtended int) error
	GetBlossomStorageQuota(pubkey []byte) (quotaMB int64, err error)
	IsFirstTimeUser(pubkey []byte) (bool, error)

	// NIP-43 Invite-based ACL
	AddNIP43Member(pubkey []byte, inviteCode string) error
	RemoveNIP43Member(pubkey []byte) error
	IsNIP43Member(pubkey []byte) (isMember bool, err error)
	GetNIP43Membership(pubkey []byte) (*NIP43Membership, error)
	GetAllNIP43Members() ([][]byte, error)
	StoreInviteCode(code string, expiresAt time.Time) error
	ValidateInviteCode(code string) (valid bool, err error)
	DeleteInviteCode(code string) error
	PublishNIP43MembershipEvent(kind int, pubkey []byte) error

	// Migrations (version tracking for schema updates)
	RunMigrations()

	// Query cache methods
	GetCachedJSON(f *filter.F) ([][]byte, bool)
	CacheMarshaledJSON(f *filter.F, marshaledJSON [][]byte)
	GetCachedEvents(f *filter.F) (event.S, bool)
	CacheEvents(f *filter.F, events event.S)
	InvalidateQueryCache()

	// Utility methods
	EventIdsBySerial(start uint64, count int) (evs []uint64, err error)
}

Database defines the interface that all database implementations must satisfy. This allows switching between different storage backends (badger, dgraph, etc.)

func NewDatabase added in v0.29.1

func NewDatabase(
	ctx context.Context,
	cancel context.CancelFunc,
	dbType string,
	dataDir string,
	logLevel string,
) (Database, error)

NewDatabase creates a database instance based on the specified type. Supported types: "badger", "dgraph", "neo4j"

func NewDatabaseWithConfig added in v0.31.8

func NewDatabaseWithConfig(
	ctx context.Context,
	cancel context.CancelFunc,
	dbType string,
	cfg *DatabaseConfig,
) (Database, error)

NewDatabaseWithConfig creates a database instance with full configuration. This is the preferred method when you have access to the app config.

type DatabaseConfig added in v0.31.8

type DatabaseConfig struct {
	// Common settings for all backends
	DataDir  string
	LogLevel string

	// Badger-specific settings
	BlockCacheMB         int           // ORLY_DB_BLOCK_CACHE_MB
	IndexCacheMB         int           // ORLY_DB_INDEX_CACHE_MB
	QueryCacheSizeMB     int           // ORLY_QUERY_CACHE_SIZE_MB
	QueryCacheMaxAge     time.Duration // ORLY_QUERY_CACHE_MAX_AGE
	InlineEventThreshold int           // ORLY_INLINE_EVENT_THRESHOLD

	// DGraph-specific settings
	DgraphURL string // ORLY_DGRAPH_URL

	// Neo4j-specific settings
	Neo4jURI      string // ORLY_NEO4J_URI
	Neo4jUser     string // ORLY_NEO4J_USER
	Neo4jPassword string // ORLY_NEO4J_PASSWORD
}

DatabaseConfig holds all database configuration options that can be passed to any database backend. Each backend uses the relevant fields for its type. This centralizes configuration instead of having each backend read env vars directly.

type EventNeedingModeration added in v0.17.0

type EventNeedingModeration struct {
	ID     string    `json:"id"`
	Reason string    `json:"reason,omitempty"`
	Added  time.Time `json:"added"`
}

EventNeedingModeration represents an event that needs moderation

type ManagedACL added in v0.17.0

type ManagedACL struct {
	*D
}

ManagedACL database operations

func NewManagedACL added in v0.17.0

func NewManagedACL(db *D) *ManagedACL

NewManagedACL creates a new ManagedACL instance

func (*ManagedACL) GetRelayConfig added in v0.17.0

func (m *ManagedACL) GetRelayConfig() (ManagedACLConfig, error)

GetRelayConfig returns relay configuration

func (*ManagedACL) IsEventAllowed added in v0.17.0

func (m *ManagedACL) IsEventAllowed(eventID string) (bool, error)

Check if an event is explicitly allowed

func (*ManagedACL) IsEventBanned added in v0.17.0

func (m *ManagedACL) IsEventBanned(eventID string) (bool, error)

Check if an event is banned

func (*ManagedACL) IsIPBlocked added in v0.17.0

func (m *ManagedACL) IsIPBlocked(ip string) (bool, error)

Check if an IP is blocked

func (*ManagedACL) IsKindAllowed added in v0.17.0

func (m *ManagedACL) IsKindAllowed(kind int) (bool, error)

Check if a kind is allowed

func (*ManagedACL) IsPubkeyAllowed added in v0.17.0

func (m *ManagedACL) IsPubkeyAllowed(pubkey string) (bool, error)

Check if a pubkey is explicitly allowed

func (*ManagedACL) IsPubkeyBanned added in v0.17.0

func (m *ManagedACL) IsPubkeyBanned(pubkey string) (bool, error)

Check if a pubkey is banned

func (*ManagedACL) ListAllowedEvents added in v0.17.0

func (m *ManagedACL) ListAllowedEvents() ([]AllowedEvent, error)

ListAllowedEvents returns all allowed events

func (*ManagedACL) ListAllowedKinds added in v0.17.0

func (m *ManagedACL) ListAllowedKinds() ([]int, error)

ListAllowedKinds returns all allowed kinds

func (*ManagedACL) ListAllowedPubkeys added in v0.17.0

func (m *ManagedACL) ListAllowedPubkeys() ([]AllowedPubkey, error)

ListAllowedPubkeys returns all allowed pubkeys

func (*ManagedACL) ListBannedEvents added in v0.17.0

func (m *ManagedACL) ListBannedEvents() ([]BannedEvent, error)

ListBannedEvents returns all banned events

func (*ManagedACL) ListBannedPubkeys added in v0.17.0

func (m *ManagedACL) ListBannedPubkeys() ([]BannedPubkey, error)

ListBannedPubkeys returns all banned pubkeys

func (*ManagedACL) ListBlockedIPs added in v0.17.0

func (m *ManagedACL) ListBlockedIPs() ([]BlockedIP, error)

ListBlockedIPs returns all blocked IPs

func (*ManagedACL) ListEventsNeedingModeration added in v0.17.0

func (m *ManagedACL) ListEventsNeedingModeration() ([]EventNeedingModeration, error)

ListEventsNeedingModeration returns all events needing moderation

func (*ManagedACL) RemoveAllowedEvent added in v0.17.0

func (m *ManagedACL) RemoveAllowedEvent(eventID string) error

RemoveAllowedEvent removes an allowed event from the database

func (*ManagedACL) RemoveAllowedKind added in v0.17.0

func (m *ManagedACL) RemoveAllowedKind(kind int) error

RemoveAllowedKind removes an allowed kind from the database

func (*ManagedACL) RemoveAllowedPubkey added in v0.17.0

func (m *ManagedACL) RemoveAllowedPubkey(pubkey string) error

RemoveAllowedPubkey removes an allowed pubkey from the database

func (*ManagedACL) RemoveBannedEvent added in v0.17.0

func (m *ManagedACL) RemoveBannedEvent(eventID string) error

RemoveBannedEvent removes a banned event from the database

func (*ManagedACL) RemoveBannedPubkey added in v0.17.0

func (m *ManagedACL) RemoveBannedPubkey(pubkey string) error

RemoveBannedPubkey removes a banned pubkey from the database

func (*ManagedACL) RemoveBlockedIP added in v0.17.0

func (m *ManagedACL) RemoveBlockedIP(ip string) error

RemoveBlockedIP removes a blocked IP from the database

func (*ManagedACL) RemoveEventNeedingModeration added in v0.17.0

func (m *ManagedACL) RemoveEventNeedingModeration(eventID string) error

RemoveEventNeedingModeration removes an event from moderation queue

func (*ManagedACL) SaveAllowedEvent added in v0.17.0

func (m *ManagedACL) SaveAllowedEvent(eventID string, reason string) error

SaveAllowedEvent saves an allowed event to the database

func (*ManagedACL) SaveAllowedKind added in v0.17.0

func (m *ManagedACL) SaveAllowedKind(kind int) error

SaveAllowedKind saves an allowed kind to the database

func (*ManagedACL) SaveAllowedPubkey added in v0.17.0

func (m *ManagedACL) SaveAllowedPubkey(pubkey string, reason string) error

SaveAllowedPubkey saves an allowed pubkey to the database

func (*ManagedACL) SaveBannedEvent added in v0.17.0

func (m *ManagedACL) SaveBannedEvent(eventID string, reason string) error

SaveBannedEvent saves a banned event to the database

func (*ManagedACL) SaveBannedPubkey added in v0.17.0

func (m *ManagedACL) SaveBannedPubkey(pubkey string, reason string) error

SaveBannedPubkey saves a banned pubkey to the database

func (*ManagedACL) SaveBlockedIP added in v0.17.0

func (m *ManagedACL) SaveBlockedIP(ip string, reason string) error

SaveBlockedIP saves a blocked IP to the database

func (*ManagedACL) SaveEventNeedingModeration added in v0.17.0

func (m *ManagedACL) SaveEventNeedingModeration(eventID string, reason string) error

SaveEventNeedingModeration saves an event that needs moderation

func (*ManagedACL) SaveRelayConfig added in v0.17.0

func (m *ManagedACL) SaveRelayConfig(config ManagedACLConfig) error

SaveRelayConfig saves relay configuration

type ManagedACLConfig added in v0.17.0

type ManagedACLConfig struct {
	RelayName        string `json:"relay_name"`
	RelayDescription string `json:"relay_description"`
	RelayIcon        string `json:"relay_icon"`
}

ManagedACLConfig represents the configuration for managed ACL mode

type NIP43Membership added in v0.27.0

type NIP43Membership struct {
	Pubkey     []byte
	AddedAt    time.Time
	InviteCode string
}

NIP43Membership represents membership metadata for NIP-43

type Payment

type Payment struct {
	Amount    int64     `json:"amount"`
	Timestamp time.Time `json:"timestamp"`
	Invoice   string    `json:"invoice"`
	Preimage  string    `json:"preimage"`
}

Payment represents a recorded payment

type Range

type Range struct {
	Start, End []byte
}

func GetIndexesFromFilter

func GetIndexesFromFilter(f *filter.F) (idxs []Range, err error)

GetIndexesFromFilter returns encoded indexes based on the given filter.

An error is returned if any input values are invalid during encoding.

The indexes are designed so that only one table needs to be iterated, being a complete set of combinations of all fields in the event, thus there is no need to decode events until they are to be delivered.

type Subscription

type Subscription struct {
	TrialEnd       time.Time `json:"trial_end"`
	PaidUntil      time.Time `json:"paid_until"`
	BlossomLevel   string    `json:"blossom_level,omitempty"`   // Service level name (e.g., "basic", "premium")
	BlossomStorage int64     `json:"blossom_storage,omitempty"` // Storage quota in MB
}

Subscription represents a user's subscription status

Source Files

  • cleanup-kind3.go
  • count.go
  • database.go
  • delete-event.go
  • delete-expired.go
  • export.go
  • factory.go
  • fetch-event-by-serial.go
  • fetch-events-by-serials.go
  • filter_utils.go
  • get-fullidpubkey-by-serial.go
  • get-fullidpubkey-by-serials.go
  • get-indexes-for-event.go
  • get-indexes-from-filter.go
  • get-serial-by-id.go
  • get-serials-by-range.go
  • identity.go
  • import.go
  • import_utils.go
  • interface.go
  • logger.go
  • managed-acl.go
  • markers.go
  • migrations.go
  • nip43.go
  • process-delete.go
  • pubkey-serial.go
  • query-events.go
  • query-for-deleted.go
  • query-for-ids.go
  • query-for-ptag-graph.go
  • query-for-serials.go
  • save-event.go
  • subscriptions.go
  • tokenize.go
  • types.go

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL