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
- Registry starts with optional admin authentication configured
- Servers and aggregators start and self-register via admin endpoint
- Clients start and self-register via public endpoint
- Services begin discovery polling after registration
- During discovery, attestation is verified before adding peers
- 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 ¶
- func AttestServiceRegistration(attestationProvider TEEProvider, r *RegisteredService) ([]byte, error)
- func ParseExchangeKey(exchangeKey string) (*ecdh.PublicKey, error)
- func ReportDataForService(exchangeKey []byte, httpEndpoint string, pubKey crypto.PublicKey) []byte
- type AggregateAggregatesRequest
- type AggregateMessageRequest
- type ClientMessageRequest
- type HTTPAggregator
- type HTTPClient
- type HTTPClientMessage
- type HTTPServer
- type InMemoryStore
- type LocalServiceRegistry
- type MeasurementEntry
- type MeasurementSource
- type MeasurementValue
- type Measurements
- type MessageResponse
- type PartialDecryptionRequest
- type PostgresConfig
- type PostgresStore
- type PublishedMeasurements
- type RegisteredService
- type Registry
- type RegistryConfig
- type RegistryStore
- type RemoteMeasurementSource
- type RoundBroadcastResponse
- type RoundOutputCallback
- type ScheduleMessageRequest
- type SecretExchangeResponse
- type ServiceConfig
- type ServiceListResponse
- type ServiceRegistrationResponse
- type ServiceType
- type StaticMeasurementSource
- type TEEProvider
- type TEEVerifier
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 ¶
ParseExchangeKey returns the parsed ECDH public key.
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.
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.
type HTTPClientMessage ¶
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.
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 ¶
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 ¶
RegisterAdminRoutes registers admin-only routes with authentication.
func (*Registry) RegisterPublicRoutes ¶
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.