nodedir

package
v0.1.0-preview.2 Latest Latest
Warning

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

Go to latest
Published: Jul 22, 2026 License: AGPL-3.0 Imports: 20 Imported by: 0

Documentation

Overview

Package nodedir implements Propagare's bounded, signed IP node directory.

The directory is a discovery and availability mechanism, not an anonymity mechanism. Node endpoints are intentionally public. Membership is admitted only through locally pinned seed identities and short-lived signed leases.

Index

Constants

View Source
const (
	ProtocolVersion      = 1
	ChallengeBytes       = 32
	MaxDirectoryNodes    = 512
	MaxAttestations      = 16
	MaxSnapshotBytes     = 16 * 1024 * 1024
	MaxRegistrationBytes = 256 * 1024
	MinLease             = 10 * time.Minute
	MaxLease             = 2 * time.Hour
	MaxClockSkew         = 5 * time.Minute
)
View Source
const MaxSeedFileBytes = 1024 * 1024

Variables

This section is empty.

Functions

func AnnouncementHash

func AnnouncementHash(announcement Announcement) []byte

func NewChallenge

func NewChallenge() ([]byte, error)

func VerifyAnnouncement

func VerifyAnnouncement(announcement Announcement, now time.Time, allowPrivate bool) error

func VerifyChallenge

func VerifyChallenge(identity protocol.NodePublicIdentity, nonce []byte, response ChallengeResponse, now time.Time) error

func VerifyRecord

func VerifyRecord(policy Policy, record Record, now time.Time) error

func VerifySnapshotHeader

func VerifySnapshotHeader(snapshot Snapshot, expectedPublisherID string, now time.Time, maxNodes int) error

Types

type Agent

type Agent struct {
	// contains filtered or unexported fields
}

func NewAgent

func NewAgent(policy Policy, endpoint Endpoint, signer Signer, lease time.Duration, client *http.Client, prober ReachabilityProber, now time.Time) (*Agent, error)

func (*Agent) AcceptRegistration

func (agent *Agent) AcceptRegistration(ctx context.Context, remoteIP netip.Addr, request RegistrationRequest, now time.Time) (Record, error)

AcceptRegistration proves that the request's TCP source owns the advertised IP, then performs a bounded callback challenge to the same IP and advertised port. Only a locally pinned seed identity can issue an admission attestation.

func (*Agent) Active

func (agent *Agent) Active(now time.Time) []Record

func (*Agent) Challenge

func (agent *Agent) Challenge(nonce []byte, now time.Time) (ChallengeResponse, error)

func (*Agent) IdentityID

func (agent *Agent) IdentityID() string

func (*Agent) Registry

func (agent *Agent) Registry() *Registry

func (*Agent) Run

func (agent *Agent) Run(ctx context.Context, interval time.Duration) error

func (*Agent) Snapshot

func (agent *Agent) Snapshot(now time.Time) (Snapshot, error)

func (*Agent) SyncOnce

func (agent *Agent) SyncOnce(ctx context.Context, now time.Time) error

type Announcement

type Announcement struct {
	Version   uint8                       `json:"version"`
	Identity  protocol.NodePublicIdentity `json:"identity"`
	Endpoint  Endpoint                    `json:"endpoint"`
	Sequence  uint64                      `json:"sequence"`
	IssuedAt  time.Time                   `json:"issued_at"`
	ExpiresAt time.Time                   `json:"expires_at"`
	Signature protocol.HybridSignature    `json:"signature"`
}

func SignAnnouncement

func SignAnnouncement(signer Signer, endpoint Endpoint, sequence uint64, now time.Time, lease time.Duration, allowPrivate bool) (Announcement, error)

type Attestation

type Attestation struct {
	Version          uint8                    `json:"version"`
	AuthorityID      string                   `json:"authority_id"`
	AnnouncementHash []byte                   `json:"announcement_hash"`
	ObservedAt       time.Time                `json:"observed_at"`
	ExpiresAt        time.Time                `json:"expires_at"`
	Signature        protocol.HybridSignature `json:"signature"`
}

func SignAttestation

func SignAttestation(signer Signer, announcement Announcement, now time.Time) (Attestation, error)

type ChallengeRequest

type ChallengeRequest struct {
	Nonce []byte `json:"nonce"`
}

type ChallengeResponse

type ChallengeResponse struct {
	Version   uint8                    `json:"version"`
	NodeID    string                   `json:"node_id"`
	Nonce     []byte                   `json:"nonce"`
	CreatedAt time.Time                `json:"created_at"`
	Signature protocol.HybridSignature `json:"signature"`
}

func SignChallenge

func SignChallenge(signer Signer, nonce []byte, now time.Time) (ChallengeResponse, error)

type Endpoint

type Endpoint struct {
	Scheme string `json:"scheme"`
	IP     string `json:"ip"`
	Port   uint16 `json:"port"`
}

func (Endpoint) BaseURL

func (endpoint Endpoint) BaseURL() string

type HTTPProber

type HTTPProber struct {
	Client *http.Client
}

func (*HTTPProber) Verify

func (prober *HTTPProber) Verify(ctx context.Context, announcement Announcement) error

type PinnedNode

type PinnedNode struct {
	Identity protocol.NodePublicIdentity `json:"identity"`
	Endpoint Endpoint                    `json:"endpoint"`
}

func DecodePinnedNodes

func DecodePinnedNodes(data []byte) ([]PinnedNode, error)

func LoadPinnedNodes

func LoadPinnedNodes(path string) ([]PinnedNode, error)

type Policy

type Policy struct {
	Seeds           []PinnedNode
	AuthorityQuorum int
	AllowPrivateIPs bool
	MaxNodes        int
}

func NewPolicy

func NewPolicy(seeds []PinnedNode, authorityQuorum int, allowPrivateIPs bool, maxNodes int) (Policy, error)

func (Policy) Authority

func (policy Policy) Authority(identity protocol.NodePublicIdentity) bool

type ReachabilityProber

type ReachabilityProber interface {
	Verify(ctx context.Context, announcement Announcement) error
}

type Record

type Record struct {
	Announcement Announcement  `json:"announcement"`
	Attestations []Attestation `json:"attestations"`
}

func CloneRecord

func CloneRecord(value Record) Record

CloneRecord returns an ownership-independent copy of a verified directory record. Consumers which retain routes must not alias snapshot buffers that a caller can later mutate.

type RegistrationRequest

type RegistrationRequest struct {
	Record Record `json:"record"`
}

type Registry

type Registry struct {
	// contains filtered or unexported fields
}

func NewRegistry

func NewRegistry(policy Policy) (*Registry, error)

func (*Registry) Active

func (registry *Registry) Active(now time.Time) []Record

func (*Registry) Merge

func (registry *Registry) Merge(record Record, now time.Time) error

Merge validates every signature before changing state. The monotonically increasing sequence prevents rollback to an older lease for the same node.

func (*Registry) MergeSnapshot

func (registry *Registry) MergeSnapshot(snapshot Snapshot, expectedPublisherID string, now time.Time) error

func (*Registry) Policy

func (registry *Registry) Policy() Policy

func (*Registry) Sweep

func (registry *Registry) Sweep(now time.Time) int

type Signer

type Signer interface {
	PublicIdentity() protocol.NodePublicIdentity
	Sign(domain string, message []byte) (protocol.HybridSignature, error)
}

type Snapshot

type Snapshot struct {
	Version     uint8                       `json:"version"`
	Publisher   protocol.NodePublicIdentity `json:"publisher"`
	GeneratedAt time.Time                   `json:"generated_at"`
	Records     []Record                    `json:"records"`
	Signature   protocol.HybridSignature    `json:"signature"`
}

func FetchSnapshot

func FetchSnapshot(ctx context.Context, client *http.Client, endpoint Endpoint, expectedPublisher protocol.NodePublicIdentity, now time.Time, maxNodes int) (Snapshot, error)

func SignSnapshot

func SignSnapshot(signer Signer, records []Record, now time.Time) (Snapshot, error)

Jump to

Keyboard shortcuts

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