services

package
v0.0.0-...-bb56c0c Latest Latest
Warning

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

Go to latest
Published: Jan 16, 2026 License: MIT Imports: 24 Imported by: 0

Documentation

Overview

Package services provides HTTP-based implementations of ADCNet protocol components with centralized service discovery and attestation verification.

Overview

This package wraps the core protocol implementations with HTTP APIs and a central registry for service discovery:

  • RESTful communication between components
  • Centralized registry for service registration and discovery
  • Attestation verification during service discovery
  • Automatic shared secret establishment via ECDH
  • Services identified by public keys
  • All messages signed and verified for integrity

Components

## Registry

The central Registry manages service discovery and registration. Services are keyed by their public key. The registry supports admin authentication for registering infrastructure services (servers, aggregators).

Public Endpoints:

  • POST /register/client - Register a client (no auth required)
  • GET /services - List all registered services
  • GET /services/{type} - List services by type
  • GET /config - Get protocol configuration
  • GET /health - Health check endpoint

Admin Endpoints (require basic auth when AdminToken is configured):

  • POST /admin/register/{service_type} - Register servers and aggregators
  • DELETE /admin/unregister/{public_key} - Remove a service

## HTTP Services

HTTPClient wraps protocol.ClientService with registry integration. Clients self-register on startup via the public endpoint. Clients poll servers for round broadcasts rather than receiving pushed updates, allowing inactive clients to naturally stop participating without cleanup.

HTTPAggregator wraps protocol.AggregatorService with registry integration. Aggregators self-register via admin endpoint with configured admin_token. Endpoints: POST /register, POST /client-messages, POST /aggregate-messages, GET /aggregates/{round}.

HTTPServer wraps protocol.ServerService with registry integration. Servers self-register via admin endpoint with configured admin_token. Endpoints: POST /register, POST /aggregate, POST /partial-decryption, GET /round-broadcast/{round}.

## Measurement Sources

MeasurementSource provides expected TEE measurements for attestation verification:

  • StaticMeasurementSource: Predefined measurements for testing/demo
  • RemoteMeasurementSource: Fetches measurements from a URL with caching
  • DemoMeasurementSource(): Factory for dummy attestation compatibility

## Service Configuration

ServiceConfig controls service behavior:

  • ADCNetConfig: Protocol parameters (round duration, message length, etc.)
  • AttestationProvider: TEE provider for generating/verifying attestations
  • AllowedMeasurementsSource: Expected measurements for peer verification
  • RegistryURL: Central registry for service discovery
  • AdminToken: Authentication for admin registration (servers/aggregators)

Configuration can be provided via YAML files:

http_addr: ":8081"
registry_url: "http://localhost:8080"
admin_token: "admin:secret"
keys:
  signing_key: ""
  exchange_key: ""
attestation:
  use_tdx: false
  measurements_url: ""
server:
  is_leader: false

## Service Lifecycle

  1. Registry starts with optional admin authentication configured
  2. Servers and aggregators start and self-register via admin endpoint
  3. Clients start and self-register via public endpoint
  4. Services begin discovery polling after registration
  5. During discovery, attestation is verified before adding peers
  6. Secret exchange uses signed requests, verified against local registry

Message Flow

  • Client Phase: Clients discover servers and aggregators, establish shared secrets via signed exchange requests, XOR-blind messages with one-time pads, and send signed messages to aggregators. Clients poll servers for previous round broadcasts to determine auction results.
  • Aggregation Phase: Aggregators discover servers, XOR client message vectors and add auction vectors in the finite field, then forward signed aggregates to all servers.
  • Server Phase: Each server removes its XOR blinding factors, servers exchange signed partial decryptions, and the leader reconstructs messages. Round broadcasts are stored and made available via GET endpoint for client polling.

Security Model

All messages are signed and verified:

  • ServiceRegistrationRequest: Signed by registrant, verified by registry
  • SecretExchangeRequest: Signed by requester, verified against attested registry
  • ClientRoundMessage: Signed by client, verified by aggregator
  • AggregatedClientMessages: Signed by aggregator, verified by servers
  • ServerPartialDecryptionMessage: Signed by server, verified by other servers
  • RoundBroadcast: Signed by leader server, verified by clients when polled

Attestation verification occurs during service discovery. All protocol messages are verified against attested keys stored in the local registry.

Security Notes

  • Ed25519 for all digital signatures
  • ECDH P-256 for key exchange and shared secret derivation
  • XOR-based one-time pad blinding per round
  • Attestation verification during service discovery
  • All messages signed and verified against attested registry
  • Requires ALL servers to participate for message recovery
  • Basic auth protects admin registration of servers and aggregators
  • Constant-time comparison for admin token verification

Performance

  • Aggregators reduce server bandwidth by O(NumClients)
  • Parallel HTTP requests for efficiency
  • Configurable round duration for throughput tuning
  • Periodic discovery polling (default: 10 minute interval)
  • Measurement source caches results for 1 hour
  • Client polling for broadcasts eliminates stale client tracking

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AttestServiceRegistration

func AttestServiceRegistration(attestationProvider TEEProvider, r *RegisteredService) ([]byte, error)

AttestServiceRegistration generates attestation evidence for a service.

func ParseExchangeKey

func ParseExchangeKey(exchangeKey string) (*ecdh.PublicKey, error)

ParseExchangeKey returns the parsed ECDH public key.

func ReportDataForService

func ReportDataForService(exchangeKey []byte, httpEndpoint string, pubKey crypto.PublicKey) []byte

ReportDataForService computes the attestation report data binding service identity.

Types

type AggregateAggregatesRequest

type AggregateAggregatesRequest struct {
	Messages []*protocol.Signed[protocol.AggregatedClientMessages] `json:"messages"`
}

AggregateAggregatesRequest wraps signed aggregates for inter-aggregator communication.

type AggregateMessageRequest

type AggregateMessageRequest struct {
	Message *protocol.Signed[protocol.AggregatedClientMessages] `json:"message"`
}

AggregateMessageRequest wraps signed aggregated messages.

type ClientMessageRequest

type ClientMessageRequest struct {
	Messages []*protocol.Signed[protocol.ClientRoundMessage] `json:"messages"`
}

ClientMessageRequest wraps signed client messages for HTTP transport.

type HTTPAggregator

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

HTTPAggregator wraps the protocol AggregatorService with HTTP endpoints.

func NewHTTPAggregator

func NewHTTPAggregator(config *ServiceConfig, signingKey crypto.PrivateKey, exchangeKey *ecdh.PrivateKey) (*HTTPAggregator, error)

NewHTTPAggregator creates an aggregator service that registers with a central registry.

func (*HTTPAggregator) PublicKey

func (a *HTTPAggregator) PublicKey() crypto.PublicKey

PublicKey returns the aggregator's signing public key.

func (*HTTPAggregator) RegisterRoutes

func (a *HTTPAggregator) RegisterRoutes(r chi.Router)

RegisterRoutes registers HTTP routes for the aggregator.

func (*HTTPAggregator) Start

func (a *HTTPAggregator) Start(ctx context.Context) error

Start registers with the central registry and begins service operations.

type HTTPClient

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

HTTPClient wraps the protocol ClientService with HTTP endpoints.

func NewHTTPClient

func NewHTTPClient(config *ServiceConfig, signingKey crypto.PrivateKey, exchangeKey *ecdh.PrivateKey) (*HTTPClient, error)

NewHTTPClient creates a client service that registers with a central registry.

func (*HTTPClient) PublicKey

func (c *HTTPClient) PublicKey() crypto.PublicKey

PublicKey returns the client's signing public key.

func (*HTTPClient) RegisterRoutes

func (c *HTTPClient) RegisterRoutes(r chi.Router)

RegisterRoutes registers HTTP routes for the client.

func (*HTTPClient) Start

func (c *HTTPClient) Start(ctx context.Context) error

Start registers with the central registry and begins service operations.

type HTTPClientMessage

type HTTPClientMessage struct {
	// Note: no integrity guarantees for the message. Should be using authenticated encryption at the protcol level.
	Message []byte
	Value   int
}

type HTTPServer

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

HTTPServer wraps the protocol ServerService with HTTP endpoints.

func NewHTTPServer

func NewHTTPServer(config *ServiceConfig, serverID protocol.ServerID, signingKey crypto.PrivateKey,
	exchangeKey *ecdh.PrivateKey, isLeader bool) (*HTTPServer, error)

NewHTTPServer creates a server service that registers with a central registry.

func (*HTTPServer) PublicKey

func (s *HTTPServer) PublicKey() crypto.PublicKey

PublicKey returns the server's signing public key.

func (*HTTPServer) RegisterRoutes

func (s *HTTPServer) RegisterRoutes(r chi.Router)

RegisterRoutes registers HTTP routes for the server.

func (*HTTPServer) ServerID

func (s *HTTPServer) ServerID() protocol.ServerID

ServerID returns the server's unique identifier.

func (*HTTPServer) SetRoundOutputCallback

func (s *HTTPServer) SetRoundOutputCallback(cb RoundOutputCallback)

SetRoundOutputCallback sets a callback invoked when rounds complete.

func (*HTTPServer) Start

func (s *HTTPServer) Start(ctx context.Context) error

Start registers with the central registry and begins service operations.

type InMemoryStore

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

InMemoryStore implements RegistryStore for testing without a database.

func NewInMemoryStore

func NewInMemoryStore() *InMemoryStore

NewInMemoryStore creates an in-memory store.

func (*InMemoryStore) DeleteService

func (s *InMemoryStore) DeleteService(publicKey string) error

DeleteService removes a service from memory.

func (*InMemoryStore) LoadAllServices

func (s *InMemoryStore) LoadAllServices() (map[ServiceType]map[string]*protocol.Signed[RegisteredService], error)

LoadAllServices returns all stored services.

func (*InMemoryStore) SaveService

func (s *InMemoryStore) SaveService(signed *protocol.Signed[RegisteredService]) error

SaveService stores a service in memory.

type LocalServiceRegistry

type LocalServiceRegistry struct {
	Clients     map[string]*protocol.Signed[RegisteredService]
	Aggregators map[string]*protocol.Signed[RegisteredService]
	Servers     map[string]*protocol.Signed[RegisteredService]
}

LocalServiceRegistry caches discovered and verified service endpoints locally.

func NewLocalServiceRegistry

func NewLocalServiceRegistry() *LocalServiceRegistry

NewLocalServiceRegistry creates an empty local service cache.

type MeasurementEntry

type MeasurementEntry struct {
	MeasurementID string                   `json:"measurement_id"`
	Measurements  map[int]MeasurementValue `json:"measurements"`
}

MeasurementEntry represents a single acceptable build configuration.

func VerifyMeasurementsMatch

func VerifyMeasurementsMatch(
	publishedAllowedMeasurements PublishedMeasurements,
	actualMeasurements Measurements,
) (MeasurementEntry, error)

func (*MeasurementEntry) ToMeasurements

func (e *MeasurementEntry) ToMeasurements() (Measurements, error)

ToMeasurements converts a MeasurementEntry to the internal format.

type MeasurementSource

type MeasurementSource interface {
	// GetAllowedMeasurements returns all acceptable measurement sets.
	GetAllowedMeasurements() (PublishedMeasurements, error)
}

MeasurementSource provides expected measurements for attestation verification.

type MeasurementValue

type MeasurementValue struct {
	Expected string `json:"expected"`
}

MeasurementValue holds an expected measurement value.

type Measurements

type Measurements map[int][]byte

Measurements maps register indices to expected measurement values.

func VerifyRegistration

func VerifyRegistration(source MeasurementSource, attestationVerifier TEEVerifier, signedReq *protocol.Signed[RegisteredService]) (Measurements, error)

VerifyRegistration verifies attestation for a signed registration.

type MessageResponse

type MessageResponse struct {
	Sent     bool                                            `json:"sent"`
	Messages []*protocol.Signed[protocol.ClientRoundMessage] `json:"messages,omitempty"`
}

MessageResponse indicates if client messages were sent.

type PartialDecryptionRequest

type PartialDecryptionRequest struct {
	Message *protocol.Signed[protocol.ServerPartialDecryptionMessage] `json:"message"`
}

PartialDecryptionRequest wraps signed partial decryption messages.

type PostgresConfig

type PostgresConfig struct {
	Host     string
	Port     int
	User     string
	Password string
	Database string
	SSLMode  string
}

PostgresConfig contains PostgreSQL connection settings.

func (*PostgresConfig) ConnectionString

func (c *PostgresConfig) ConnectionString() string

ConnectionString returns the PostgreSQL connection string.

type PostgresStore

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

PostgresStore implements RegistryStore with PostgreSQL persistence.

func NewPostgresStore

func NewPostgresStore(config *PostgresConfig) (*PostgresStore, error)

NewPostgresStore creates a new PostgreSQL-backed store.

func (*PostgresStore) Close

func (s *PostgresStore) Close() error

Close closes the database connection.

func (*PostgresStore) DeleteService

func (s *PostgresStore) DeleteService(publicKey string) error

DeleteService removes a service registration.

func (*PostgresStore) LoadAllServices

func (s *PostgresStore) LoadAllServices() (map[ServiceType]map[string]*protocol.Signed[RegisteredService], error)

LoadAllServices retrieves all persisted service registrations.

func (*PostgresStore) SaveService

func (s *PostgresStore) SaveService(signed *protocol.Signed[RegisteredService]) error

SaveService persists a signed service registration.

type PublishedMeasurements

type PublishedMeasurements []MeasurementEntry

PublishedMeasurements contains attestation measurements for released builds. Fetched from a public URL and used for client-side attestation verification.

JSON format:

[
  {
    "measurement_id": "adcnet-v0.0.1-tdx-abc123...",
    "measurements": {
      0: {"expected": "hex-encoded-mrtd..."},
      1: {"expected": "hex-encoded-rtmr0..."},
      2: {"expected": "hex-encoded-rtmr1..."}
      3: {"expected": "hex-encoded-rtmr2..."}
    }
  }
]

The file is an array of MeasurementEntry objects. Each entry represents an acceptable build. Keys in "measurements" are register indices. A service is accepted if its attestation matches any entry in the array.

type RegisteredService

type RegisteredService struct {
	ServiceType  ServiceType `json:"service_type"`
	HTTPEndpoint string      `json:"http_endpoint"`
	PublicKey    string      `json:"public_key"`
	ExchangeKey  string      `json:"exchange_key"`
	Attestation  []byte      `json:"attestation,omitempty"`
}

RegisteredService contains all registration data for a service instance. This is the canonical type used throughout the system for service identity.

func (*RegisteredService) ParsePublicKey

func (s *RegisteredService) ParsePublicKey() (crypto.PublicKey, error)

ParsePublicKey returns the parsed signing public key.

type Registry

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

Registry manages service discovery and registration for ADCNet components.

func NewRegistry

func NewRegistry(config *RegistryConfig, adcConfig *protocol.ADCNetConfig) (*Registry, error)

NewRegistry creates a registry with the given configuration.

func (*Registry) RegisterAdminRoutes

func (r *Registry) RegisterAdminRoutes(router chi.Router)

RegisterAdminRoutes registers admin-only routes with authentication.

func (*Registry) RegisterPublicRoutes

func (r *Registry) RegisterPublicRoutes(router chi.Router)

RegisterPublicRoutes registers public routes.

type RegistryConfig

type RegistryConfig struct {
	MeasurementSource   MeasurementSource
	AttestationVerifier TEEVerifier
	Store               RegistryStore
	// AdminToken requires basic auth for admin operations when set.
	AdminToken string
}

RegistryConfig configures the registry.

type RegistryStore

type RegistryStore interface {
	SaveService(signed *protocol.Signed[RegisteredService]) error
	DeleteService(publicKey string) error
	LoadAllServices() (map[ServiceType]map[string]*protocol.Signed[RegisteredService], error)
}

RegistryStore abstracts persistence for registered services.

type RemoteMeasurementSource

type RemoteMeasurementSource struct {
	URL        string
	HTTPClient *http.Client
	// contains filtered or unexported fields
}

RemoteMeasurementSource fetches measurements from a URL.

func NewRemoteMeasurementSource

func NewRemoteMeasurementSource(url string) *RemoteMeasurementSource

NewRemoteMeasurementSource creates a source that fetches from a URL.

func (*RemoteMeasurementSource) GetAllowedMeasurements

func (r *RemoteMeasurementSource) GetAllowedMeasurements() (PublishedMeasurements, error)

GetAllowedMeasurements fetches and returns all acceptable measurement sets.

type RoundBroadcastResponse

type RoundBroadcastResponse struct {
	Broadcast *protocol.Signed[protocol.RoundBroadcast] `json:"broadcast"`
}

RoundBroadcastResponse wraps signed round broadcast results.

type RoundOutputCallback

type RoundOutputCallback func(*protocol.RoundBroadcast)

RoundOutputCallback is invoked when a round broadcast is finalized.

type ScheduleMessageRequest

type ScheduleMessageRequest struct {
	Message  []byte `json:"message"`
	BidValue uint32 `json:"bid_value"`
}

ScheduleMessageRequest schedules a message for broadcast.

type SecretExchangeResponse

type SecretExchangeResponse struct {
	Success bool   `json:"success"`
	Message string `json:"message,omitempty"`
}

SecretExchangeResponse confirms shared secret establishment.

type ServiceConfig

type ServiceConfig struct {
	ADCNetConfig              *protocol.ADCNetConfig
	AttestationProvider       TEEProvider
	AllowedMeasurementsSource MeasurementSource
	HTTPAddr                  string
	ServiceType               ServiceType
	RegistryURL               string
	// AdminToken for authenticating with registry admin endpoints (user:pass).
	AdminToken string
}

ServiceConfig contains configuration for HTTP services.

type ServiceListResponse

type ServiceListResponse struct {
	Servers     []*protocol.Signed[RegisteredService] `json:"servers"`
	Aggregators []*protocol.Signed[RegisteredService] `json:"aggregators"`
	Clients     []*protocol.Signed[RegisteredService] `json:"clients"`
}

ServiceListResponse contains all registered services by type.

type ServiceRegistrationResponse

type ServiceRegistrationResponse struct {
	Success   bool   `json:"success"`
	PublicKey string `json:"public_key,omitempty"`
	Message   string `json:"message,omitempty"`
}

ServiceRegistrationResponse confirms registry registration.

type ServiceType

type ServiceType string

ServiceType identifies the type of service.

const (
	ClientService     ServiceType = "client"
	AggregatorService ServiceType = "aggregator"
	ServerService     ServiceType = "server"
)

func (ServiceType) Valid

func (t ServiceType) Valid() bool

Valid returns true if the service type is recognized.

type StaticMeasurementSource

type StaticMeasurementSource struct {
	Measurements PublishedMeasurements
}

StaticMeasurementSource provides measurements from a static configuration. Useful for testing and demo deployments where TEE measurements are known in advance or when using dummy attestation.

func DemoMeasurementSource

func DemoMeasurementSource() *StaticMeasurementSource

DemoMeasurementSource returns a MeasurementSource that accepts dummy attestations. The returned measurements match the values produced by tdx.DummyProvider. Only use in demo/testing environments.

func NewStaticMeasurementSource

func NewStaticMeasurementSource(measurements PublishedMeasurements) *StaticMeasurementSource

NewStaticMeasurementSource creates a source with predefined measurements.

func (*StaticMeasurementSource) GetAllowedMeasurements

func (s *StaticMeasurementSource) GetAllowedMeasurements() (PublishedMeasurements, error)

GetAllowedMeasurements returns the static measurement sets.

type TEEProvider

type TEEProvider interface {
	TEEVerifier
	AttestationType() string
	Attest(reportData [64]byte) ([]byte, error)
}

TEEProvider abstracts attestation generation and verification.

type TEEVerifier

type TEEVerifier interface {
	Verify(attestationReport []byte, expectedReportData [64]byte) (map[int][]byte, error)
}

Jump to

Keyboard shortcuts

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