Documentation
¶
Index ¶
- Constants
- func CommonPrefixLen(a, b NodeID) int
- func DefaultBootstrapNodes() []string
- func Less(a, b NodeID) bool
- func MinePoW(pubKey string, difficulty int) uint64
- func ValidatePoW(pubKey string, nonce uint64, difficulty int) bool
- type BootstrapConfig
- type DHT
- func (d *DHT) Bootstrap(ctx context.Context, seeds []NodeInfo) error
- func (d *DHT) FindNode(ctx context.Context, target NodeID) ([]NodeInfo, error)
- func (d *DHT) Get(ctx context.Context, key string) ([]byte, error)
- func (d *DHT) LocalStore() *Store
- func (d *DHT) Put(ctx context.Context, key string, value []byte) error
- func (d *DHT) RoutingTable() *RoutingTable
- func (d *DHT) Self() NodeInfo
- func (d *DHT) Start(ctx context.Context) error
- func (d *DHT) Stop() error
- type DHTTransport
- type InMemoryTransport
- func (t *InMemoryTransport) Close() error
- func (t *InMemoryTransport) Connect(other *InMemoryTransport)
- func (t *InMemoryTransport) DeliverResponse(target NodeInfo, resp *RPCResponse)
- func (t *InMemoryTransport) Listen(ctx context.Context) (<-chan RPCMessage, error)
- func (t *InMemoryTransport) SendRPC(ctx context.Context, target NodeInfo, msg RPCMessage) (*RPCResponse, error)
- type NodeID
- type NodeInfo
- type NostrDHTTransport
- type RPCMessage
- type RPCResponse
- type RPCType
- type RoutingTable
- func (rt *RoutingTable) AddNode(node NodeInfo) bool
- func (rt *RoutingTable) AllNodes() []NodeInfo
- func (rt *RoutingTable) BucketsNeedingRefresh(maxAge time.Duration) []int
- func (rt *RoutingTable) FindClosest(target NodeID, count int) []NodeInfo
- func (rt *RoutingTable) GetNode(id NodeID) (NodeInfo, bool)
- func (rt *RoutingTable) RemoveNode(id NodeID) bool
- func (rt *RoutingTable) SelfID() NodeID
- func (rt *RoutingTable) SetPingFunc(fn func(ctx context.Context, node NodeInfo) bool)
- func (rt *RoutingTable) SetPoWRequired(required bool, difficulty int)
- func (rt *RoutingTable) Size() int
- type Store
- func (s *Store) CleanExpired() int
- func (s *Store) Delete(key string)
- func (s *Store) Get(key string) []byte
- func (s *Store) Has(key string) bool
- func (s *Store) Keys() []string
- func (s *Store) LoadFromFile(path string) error
- func (s *Store) Put(key string, value []byte, ttl time.Duration, sender string) error
- func (s *Store) SaveToFile(path string) error
- func (s *Store) Size() int
- type StoreOption
Constants ¶
const ( // Alpha is the Kademlia concurrency parameter. Alpha = 3 // RefreshInterval is how often buckets are refreshed. RefreshInterval = 1 * time.Hour // RepublishInterval is how often stored data is republished. RepublishInterval = 1 * time.Hour )
const ( // IDLength is the length of a NodeID in bytes (160-bit SHA-1). IDLength = 20 // IDBits is the length of a NodeID in bits. IDBits = IDLength * 8 )
const ( // K is the Kademlia replication parameter (max nodes per bucket). K = 20 // BucketCount is the number of k-buckets (one per bit of NodeID). BucketCount = IDBits )
const DefaultPoWDifficulty = 16
DefaultPoWDifficulty is the default number of leading zero bits required for PoW.
const DefaultTTL = 1 * time.Hour
DefaultTTL is the default time-to-live for stored values.
const NostrDHTEventKind = 20005
NostrDHTEventKind is the Nostr event kind used for DHT RPC messages.
Variables ¶
This section is empty.
Functions ¶
func CommonPrefixLen ¶
CommonPrefixLen returns the number of leading zero bits in the XOR distance, which corresponds to the bucket index in the routing table.
func DefaultBootstrapNodes ¶
func DefaultBootstrapNodes() []string
DefaultBootstrapNodes returns the default list of bootstrap nodes. These are well-known Nostr relay URLs that serve as initial entry points.
func Less ¶
Less returns true if distance a is less than distance b (as big-endian unsigned integers).
Types ¶
type BootstrapConfig ¶
type BootstrapConfig struct {
// Seeds are the addresses of seed nodes to contact.
Seeds []string
// NostrRelays are Nostr relays to use for DHT transport.
NostrRelays []string
}
BootstrapConfig holds configuration for DHT bootstrapping.
type DHT ¶
type DHT struct {
// contains filtered or unexported fields
}
DHT implements a minimal Kademlia distributed hash table.
func NewDHT ¶
func NewDHT(self NodeInfo, transport DHTTransport, logger *slog.Logger, keypair ...*coreidentity.Keypair) *DHT
NewDHT creates a new DHT node. An optional keypair can be provided for message signing and verification.
func (*DHT) Put ¶
Put stores a value in the DHT. The value is stored locally and at the k closest nodes to the key.
func (*DHT) RoutingTable ¶
func (d *DHT) RoutingTable() *RoutingTable
RoutingTable returns the DHT routing table.
type DHTTransport ¶
type DHTTransport interface {
SendRPC(ctx context.Context, target NodeInfo, msg RPCMessage) (*RPCResponse, error)
Listen(ctx context.Context) (<-chan RPCMessage, error)
Close() error
}
DHTTransport abstracts the network layer for DHT RPC communication.
type InMemoryTransport ¶
type InMemoryTransport struct {
// contains filtered or unexported fields
}
InMemoryTransport is a DHTTransport for testing that routes messages in-process.
func NewInMemoryTransport ¶
func NewInMemoryTransport(self NodeInfo, logger *slog.Logger) *InMemoryTransport
NewInMemoryTransport creates a new in-memory transport for testing.
func (*InMemoryTransport) Close ¶
func (t *InMemoryTransport) Close() error
Close closes the transport.
func (*InMemoryTransport) Connect ¶
func (t *InMemoryTransport) Connect(other *InMemoryTransport)
Connect links two in-memory transports for bidirectional communication.
func (*InMemoryTransport) DeliverResponse ¶
func (t *InMemoryTransport) DeliverResponse(target NodeInfo, resp *RPCResponse)
DeliverResponse sends a response back to the requester.
func (*InMemoryTransport) Listen ¶
func (t *InMemoryTransport) Listen(ctx context.Context) (<-chan RPCMessage, error)
Listen returns the channel of incoming RPC messages.
func (*InMemoryTransport) SendRPC ¶
func (t *InMemoryTransport) SendRPC(ctx context.Context, target NodeInfo, msg RPCMessage) (*RPCResponse, error)
SendRPC sends a message and waits for a response.
type NodeID ¶
NodeID is a 160-bit identifier for a DHT node, derived from SHA-1 of the public key.
func NodeIDFromHex ¶
NodeIDFromHex parses a hex-encoded NodeID.
func NodeIDFromPublicKey ¶
NodeIDFromPublicKey derives a NodeID from an agent's public key string.
func XORDistance ¶
XORDistance computes the XOR distance between two NodeIDs.
type NodeInfo ¶
type NodeInfo struct {
ID NodeID `json:"id"`
PublicKey string `json:"public_key"`
Address string `json:"address,omitempty"`
Relays []string `json:"relays,omitempty"`
Nonce uint64 `json:"nonce,omitempty"`
LastSeen time.Time `json:"last_seen"`
}
NodeInfo contains the identity and network information of a DHT node.
type NostrDHTTransport ¶
type NostrDHTTransport struct {
// contains filtered or unexported fields
}
NostrDHTTransport implements DHTTransport using Nostr ephemeral events. Uses event kind 20005, NIP-44 encryption, reusing the NostrTransport relay management pattern.
func NewNostrDHTTransport ¶
func NewNostrDHTTransport(self NodeInfo, relayURLs []string, logger *slog.Logger) *NostrDHTTransport
NewNostrDHTTransport creates a new Nostr-based DHT transport.
func (*NostrDHTTransport) Close ¶
func (t *NostrDHTTransport) Close() error
Close closes the transport and disconnects from relays.
func (*NostrDHTTransport) Listen ¶
func (t *NostrDHTTransport) Listen(ctx context.Context) (<-chan RPCMessage, error)
Listen returns a channel of incoming DHT RPC messages.
func (*NostrDHTTransport) SendRPC ¶
func (t *NostrDHTTransport) SendRPC(ctx context.Context, target NodeInfo, msg RPCMessage) (*RPCResponse, error)
SendRPC sends a DHT RPC message via Nostr relay and waits for a response.
type RPCMessage ¶
type RPCMessage struct {
Type RPCType `json:"type"`
RequestID string `json:"request_id"`
Sender NodeInfo `json:"sender"`
Target NodeID `json:"target,omitempty"` // For find_node/find_value
Key string `json:"key,omitempty"` // For store/find_value
Value json.RawMessage `json:"value,omitempty"` // For store
Signature string `json:"signature,omitempty"`
}
RPCMessage is a DHT RPC request sent between nodes.
func (RPCMessage) SigningPayload ¶
func (m RPCMessage) SigningPayload() []byte
SigningPayload returns the RPCMessage serialized without the Signature field, suitable for signing and verification.
type RPCResponse ¶
type RPCResponse struct {
RequestID string `json:"request_id"`
Sender NodeInfo `json:"sender"`
Nodes []NodeInfo `json:"nodes,omitempty"` // For find_node
Value json.RawMessage `json:"value,omitempty"` // For find_value
Found bool `json:"found,omitempty"` // For find_value
Error string `json:"error,omitempty"`
Signature string `json:"signature,omitempty"`
}
RPCResponse is a DHT RPC response.
func (RPCResponse) SigningPayload ¶
func (r RPCResponse) SigningPayload() []byte
SigningPayload returns the RPCResponse serialized without the Signature field, suitable for signing and verification.
type RoutingTable ¶
type RoutingTable struct {
// contains filtered or unexported fields
}
RoutingTable is a Kademlia routing table with BucketCount k-buckets.
func NewRoutingTable ¶
func NewRoutingTable(self NodeID) *RoutingTable
NewRoutingTable creates a routing table for the given node.
func (*RoutingTable) AddNode ¶
func (rt *RoutingTable) AddNode(node NodeInfo) bool
AddNode inserts or updates a node in the routing table. If PoW is required, the node must present a valid proof-of-work. If the appropriate bucket is full, the least-recently-seen node is pinged; if it does not respond, it is evicted and the new node is inserted.
func (*RoutingTable) AllNodes ¶
func (rt *RoutingTable) AllNodes() []NodeInfo
AllNodes returns all nodes in the routing table.
func (*RoutingTable) BucketsNeedingRefresh ¶
func (rt *RoutingTable) BucketsNeedingRefresh(maxAge time.Duration) []int
BucketsNeedingRefresh returns bucket indices that haven't been refreshed within the given duration.
func (*RoutingTable) FindClosest ¶
func (rt *RoutingTable) FindClosest(target NodeID, count int) []NodeInfo
FindClosest returns the k closest nodes to the given target ID.
func (*RoutingTable) GetNode ¶
func (rt *RoutingTable) GetNode(id NodeID) (NodeInfo, bool)
GetNode looks up a specific node by ID.
func (*RoutingTable) RemoveNode ¶
func (rt *RoutingTable) RemoveNode(id NodeID) bool
RemoveNode removes a node from the routing table.
func (*RoutingTable) SelfID ¶
func (rt *RoutingTable) SelfID() NodeID
SelfID returns the local node's ID.
func (*RoutingTable) SetPingFunc ¶
func (rt *RoutingTable) SetPingFunc(fn func(ctx context.Context, node NodeInfo) bool)
SetPingFunc sets the function used to ping nodes when a bucket is full.
func (*RoutingTable) SetPoWRequired ¶
func (rt *RoutingTable) SetPoWRequired(required bool, difficulty int)
SetPoWRequired enables or disables proof-of-work validation for new nodes.
func (*RoutingTable) Size ¶
func (rt *RoutingTable) Size() int
Size returns the total number of nodes in the routing table.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store is a local key-value store for DHT data with TTL-based expiration.
func (*Store) CleanExpired ¶
CleanExpired removes all expired entries.
func (*Store) LoadFromFile ¶
LoadFromFile loads the store from a JSON file.
func (*Store) Put ¶
Put stores a value with a key and TTL. The sender parameter identifies the peer that is storing the value for per-peer quota enforcement. Returns an error if value exceeds size limits or sender has exceeded quota.
func (*Store) SaveToFile ¶
SaveToFile persists the store to a JSON file.
type StoreOption ¶
type StoreOption func(*Store)
StoreOption configures a Store.
func WithMaxEntries ¶
func WithMaxEntries(n int) StoreOption
WithMaxEntries sets the maximum number of entries in the store.
func WithMaxPerPeer ¶
func WithMaxPerPeer(n int) StoreOption
WithMaxPerPeer sets the maximum number of entries a single peer can store.
func WithMaxValueSize ¶
func WithMaxValueSize(n int) StoreOption
WithMaxValueSize sets the maximum size of a single stored value in bytes.