Documentation
¶
Overview ¶
Package protocol implements ADCNet: an anonymous distributed communication network using XOR-based message blinding and auction-based message scheduling.
Protocol Overview ¶
ADCNet provides anonymous broadcast with the following key features:
- XOR-based blinding for message privacy requiring all servers
- Auction-based scheduling using Invertible Bloom Lookup Tables (IBLT)
Architecture ¶
The protocol operates through three main components:
Clients: Blind their messages with XOR using one-time pads derived from shared secrets with all servers. Auction bids use field arithmetic blinding.
Aggregators: Combine client messages by XORing message vectors and adding auction vectors in the finite field. This reduces bandwidth to servers.
Servers: Each server removes its blinding factors from the aggregate. Messages are recovered by XORing all server contributions. Auction IBLT is recovered using field subtraction.
Core Protocol Flow ¶
1. Message Preparation (Client):
- Client determines if it won a slot in the previous round's auction
- Encodes message at the auction-determined byte offset if so
- Blinds message with XOR using one-time pads from all server shared secrets
- Blinds auction IBLT with field addition using server-specific pads
2. Aggregation:
- Aggregators XOR client message vectors together
- Aggregators add blinded client auction vectors
- Multiple aggregation levels can reduce bandwidth hierarchically
3. Unblinding (Server):
- Each server derives its blinding contribution from shared secrets
- Server sends XOR of all its XOR blinding vectors for messages and its field element blinding vector for auction and forwards to leader
4. Reconstruction:
- XOR all server message blindings with aggregate to recover messages
- Subtract all server auction blindings from aggregate to recover IBLT
- Decode auction IBLT to determine next round's winners
Security Properties ¶
- Anonymity: Sender identity protected if at least one server is honest
- Privacy: Message content hidden unless all servers collude
- Unlinkability: Fresh blinding prevents correlation between rounds
Index ¶
- func AuctionSlotsForConfig(c *ADCNetConfig) uint32
- func DecodeMessage[T any](reader io.Reader) (*T, error)
- func SerializeMessage[T any](msg *T) ([]byte, error)
- func TimeForRound(round Round, roundDuration time.Duration) time.Time
- func UnmarshalMessage[T any](data []byte) (*T, error)
- type ADCNetConfig
- type AggregatedClientMessages
- type AggregatorMessager
- type AggregatorRoundData
- type AggregatorService
- func (a *AggregatorService) AdvanceToRound(round Round)
- func (a *AggregatorService) CurrentAggregates() *AggregatedClientMessages
- func (a *AggregatorService) DeregisterClient(pubkey crypto.PublicKey) error
- func (a *AggregatorService) ProcessClientMessages(msgs []*Signed[ClientRoundMessage]) (*AggregatedClientMessages, error)
- func (a *AggregatorService) ProcessVerifiedMessages(verified []VerifiedClientMessage) (*AggregatedClientMessages, error)
- func (a *AggregatorService) RegisterClient(pubkey crypto.PublicKey) error
- type AuctionResult
- type ClientMessager
- func (c *ClientMessager) BlindClientMessage(currentRound int, messageVector []byte, auctionElements []*big.Int) (*ClientRoundMessage, error)
- func (c *ClientMessager) PrepareMessage(currentRound int, previousRoundOutput *RoundBroadcast, ...) (*ClientRoundMessage, bool, error)
- func (c *ClientMessager) ProcessPreviousAuction(auctionIBLT *blind_auction.IBLTVector, previousRoundMessage []byte) AuctionResult
- type ClientRoundMessage
- type ClientService
- func (c *ClientService) AdvanceToRound(round Round)
- func (c *ClientService) DeregisterServer(serverId ServerID) error
- func (c *ClientService) MessagesForCurrentRound() (*Signed[ClientRoundMessage], bool, error)
- func (c *ClientService) ProcessRoundBroadcast(rb *RoundBroadcast) error
- func (c *ClientService) RegisterServer(serverId ServerID, serverExchangePubkey *ecdh.PublicKey) error
- func (c *ClientService) ScheduleMessageForNextRound(msg []byte, bidValue uint32) error
- type LocalRoundCoordinator
- type PendingMessage
- type Round
- type RoundBroadcast
- type RoundContext
- type RoundCoordinator
- type ScheduledMessage
- type ServerID
- type ServerMessager
- type ServerPartialDecryptionMessage
- type ServerRoundData
- type ServerService
- func (s *ServerService) AdvanceToRound(round Round)
- func (s *ServerService) DeregisterClient(clientPubkey crypto.PublicKey) error
- func (s *ServerService) ProcessAggregateMessage(msg *AggregatedClientMessages) (*ServerPartialDecryptionMessage, error)
- func (s *ServerService) ProcessPartialDecryptionMessage(msg *ServerPartialDecryptionMessage) (*RoundBroadcast, error)
- func (s *ServerService) RegisterClient(clientPubkey crypto.PublicKey, clientECDHPubkey *ecdh.PublicKey) error
- type Signed
- type VerifiedClientMessage
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AuctionSlotsForConfig ¶
func AuctionSlotsForConfig(c *ADCNetConfig) uint32
AuctionSlotsForConfig calculates total IBLT vector size for the configuration.
func DecodeMessage ¶
DecodeMessage deserializes a message from a JSON reader.
func SerializeMessage ¶
SerializeMessage serializes a message to JSON.
func TimeForRound ¶
TimeForRound returns the start time for a given round.
func UnmarshalMessage ¶
UnmarshalMessage deserializes a message from JSON.
Types ¶
type ADCNetConfig ¶
type ADCNetConfig struct {
// AuctionSlots is the number of slots in the IBLT for auction data.
AuctionSlots uint32 `json:"auction_slots"`
// MessageLength is the maximum byte capacity of the message vector.
// Actual per-round length is determined by auction results.
MessageLength int `json:"message_length"`
// MinClients is the minimum number of clients for anonymity.
MinClients uint32 `json:"min_clients"`
// RoundDuration is the time duration of each protocol round.
RoundDuration time.Duration `json:"round_duration,string"`
// RoundsPerWindow defines rounds per participation window for rate limiting.
RoundsPerWindow uint32 `json:"rounds_per_window"`
}
ADCNetConfig provides configuration parameters for ADCNet components.
type AggregatedClientMessages ¶
type AggregatedClientMessages struct {
RoundNumber int
AllServerIds []ServerID
AuctionVector []*big.Int // Sum of client auction vectors in field
MessageVector []byte // XOR of client message vectors
UserPKs []crypto.PublicKey // Public keys of contributing clients
}
AggregatedClientMessages contains combined data from multiple clients.
func (*AggregatedClientMessages) UnionInplace ¶
func (m *AggregatedClientMessages) UnionInplace(o *AggregatedClientMessages) (*AggregatedClientMessages, error)
UnionInplace adds another aggregate's vectors to this one in-place. XORs message vectors and adds auction vectors in the finite field.
type AggregatorMessager ¶
type AggregatorMessager struct {
Config *ADCNetConfig
}
AggregatorMessager implements message aggregation operations.
func (*AggregatorMessager) AggregateAggregates ¶
func (a *AggregatorMessager) AggregateAggregates(round int, msgs []*AggregatedClientMessages) (*AggregatedClientMessages, error)
AggregateAggregates combines multiple aggregated messages into one.
func (*AggregatorMessager) AggregateVerifiedMessages ¶
func (a *AggregatorMessager) AggregateVerifiedMessages(round int, previousAggregate *AggregatedClientMessages, verified []VerifiedClientMessage, authorizedClients map[string]bool) (*AggregatedClientMessages, error)
AggregateVerifiedMessages combines pre-verified client messages into a single aggregate.
type AggregatorRoundData ¶
type AggregatorRoundData struct {
Round int
Aggregate *AggregatedClientMessages
}
AggregatorRoundData holds per-round aggregation state.
type AggregatorService ¶
type AggregatorService struct {
// contains filtered or unexported fields
}
AggregatorService combines client messages to reduce bandwidth to servers.
func NewAggregatorService ¶
func NewAggregatorService(config *ADCNetConfig) *AggregatorService
NewAggregatorService creates an aggregator service.
func (*AggregatorService) AdvanceToRound ¶
func (a *AggregatorService) AdvanceToRound(round Round)
AdvanceToRound transitions the aggregator to a new protocol round.
func (*AggregatorService) CurrentAggregates ¶
func (a *AggregatorService) CurrentAggregates() *AggregatedClientMessages
CurrentAggregates returns the current round's aggregate.
func (*AggregatorService) DeregisterClient ¶
func (a *AggregatorService) DeregisterClient(pubkey crypto.PublicKey) error
DeregisterClient removes a client's authorization.
func (*AggregatorService) ProcessClientMessages ¶
func (a *AggregatorService) ProcessClientMessages(msgs []*Signed[ClientRoundMessage]) (*AggregatedClientMessages, error)
ProcessClientMessages verifies and aggregates signed client messages.
func (*AggregatorService) ProcessVerifiedMessages ¶
func (a *AggregatorService) ProcessVerifiedMessages(verified []VerifiedClientMessage) (*AggregatedClientMessages, error)
ProcessVerifiedMessages aggregates pre-verified client messages.
func (*AggregatorService) RegisterClient ¶
func (a *AggregatorService) RegisterClient(pubkey crypto.PublicKey) error
RegisterClient authorizes a client to submit messages.
type AuctionResult ¶
type AuctionResult struct {
// ShouldSend indicates if the client won a slot.
ShouldSend bool
// MessageStartIndex is the byte offset where the message should be placed.
MessageStartIndex int
// TotalAllocated indicates how many total bytes have been allocated by the auction
TotalAllocated int
}
AuctionResult indicates whether a client won an auction slot.
type ClientMessager ¶
type ClientMessager struct {
Config *ADCNetConfig
}
ClientMessager implements client-side message preparation with XOR blinding.
func ClientSetup ¶
func ClientSetup(config *ADCNetConfig, serverPubkeys map[ServerID]*ecdh.PublicKey, clientPrivkey *ecdh.PrivateKey) (*ClientMessager, error)
ClientSetup creates a ClientMessager by deriving shared secrets with all servers.
func (*ClientMessager) BlindClientMessage ¶
func (c *ClientMessager) BlindClientMessage(currentRound int, messageVector []byte, auctionElements []*big.Int) (*ClientRoundMessage, error)
BlindClientMessage applies XOR blinding to message and field-element blinding to auction data.
func (*ClientMessager) PrepareMessage ¶
func (c *ClientMessager) PrepareMessage(currentRound int, previousRoundOutput *RoundBroadcast, previousRoundMessage []byte, currentRoundAuctionData *blind_auction.AuctionData) (*ClientRoundMessage, bool, error)
PrepareMessage creates a blinded message with auction data for the current round.
func (*ClientMessager) ProcessPreviousAuction ¶
func (c *ClientMessager) ProcessPreviousAuction(auctionIBLT *blind_auction.IBLTVector, previousRoundMessage []byte) AuctionResult
ProcessPreviousAuction determines if this client won a slot in the auction.
type ClientRoundMessage ¶
type ClientRoundMessage struct {
RoundNumber int
AllServerIds []ServerID
AuctionVector []*big.Int // Field-blinded auction IBLT elements
MessageVector []byte // XOR-blinded message bytes
}
ClientRoundMessage contains a client's blinded message and auction data.
type ClientService ¶
type ClientService struct {
// contains filtered or unexported fields
}
ClientService manages client-side protocol operations.
func NewClientService ¶
func NewClientService(config *ADCNetConfig, signingKey crypto.PrivateKey, exchangeKey *ecdh.PrivateKey) *ClientService
NewClientService creates a client service.
func (*ClientService) AdvanceToRound ¶
func (c *ClientService) AdvanceToRound(round Round)
AdvanceToRound transitions the client to a new protocol round.
func (*ClientService) DeregisterServer ¶
func (c *ClientService) DeregisterServer(serverId ServerID) error
DeregisterServer removes a server's shared secret.
func (*ClientService) MessagesForCurrentRound ¶
func (c *ClientService) MessagesForCurrentRound() (*Signed[ClientRoundMessage], bool, error)
MessagesForCurrentRound generates the blinded message for the current round. Returns the signed message, whether a scheduled message won its auction, and any error.
func (*ClientService) ProcessRoundBroadcast ¶
func (c *ClientService) ProcessRoundBroadcast(rb *RoundBroadcast) error
ProcessRoundBroadcast stores the reconstructed broadcast for auction resolution.
func (*ClientService) RegisterServer ¶
func (c *ClientService) RegisterServer(serverId ServerID, serverExchangePubkey *ecdh.PublicKey) error
RegisterServer establishes a shared secret with a server via ECDH.
func (*ClientService) ScheduleMessageForNextRound ¶
func (c *ClientService) ScheduleMessageForNextRound(msg []byte, bidValue uint32) error
ScheduleMessageForNextRound queues a message with a bid value for the auction. The auction bid will be submitted in the current round's MessagesForCurrentRound call; if won, the message transmits in the following round.
type LocalRoundCoordinator ¶
type LocalRoundCoordinator struct {
// contains filtered or unexported fields
}
LocalRoundCoordinator provides deterministic round advancement.
func NewLocalRoundCoordinator ¶
func NewLocalRoundCoordinator(roundDuration time.Duration) *LocalRoundCoordinator
NewLocalRoundCoordinator creates a time-based round coordinator.
func (*LocalRoundCoordinator) AdvanceToRound ¶
func (c *LocalRoundCoordinator) AdvanceToRound(round Round)
AdvanceToRound manually advances to a specific round (for testing).
func (*LocalRoundCoordinator) CurrentRound ¶
func (c *LocalRoundCoordinator) CurrentRound() Round
CurrentRound returns the current protocol round number.
func (*LocalRoundCoordinator) Start ¶
func (c *LocalRoundCoordinator) Start(ctx context.Context)
Start begins round progression.
func (*LocalRoundCoordinator) SubscribeToRounds ¶
func (c *LocalRoundCoordinator) SubscribeToRounds(ctx context.Context) <-chan Round
SubscribeToRounds returns a channel that receives round transition notifications.
type PendingMessage ¶
type PendingMessage struct {
Message []byte
AuctionData *blind_auction.AuctionData
}
PendingMessage represents a message submitted by the user, awaiting auction bid submission.
type Round ¶
type Round struct {
Number int
Context RoundContext
}
Round represents a protocol round with its phase context.
func RoundForTime ¶
RoundForTime calculates the round for a given instant.
type RoundBroadcast ¶
type RoundBroadcast struct {
RoundNumber int
AuctionVector *blind_auction.IBLTVector
MessageVector []byte
}
RoundBroadcast contains the final reconstructed broadcast for a round.
type RoundContext ¶
type RoundContext int
RoundContext represents the phase within a protocol round.
const ( ClientRoundContext RoundContext = iota AggregatorRoundContext ServerPartialRoundContext ServerLeaderRoundContext )
type RoundCoordinator ¶
type RoundCoordinator interface {
CurrentRound() Round
SubscribeToRounds(ctx context.Context) <-chan Round
Start(ctx context.Context)
AdvanceToRound(round Round)
}
RoundCoordinator manages protocol round transitions.
type ScheduledMessage ¶
type ScheduledMessage struct {
Message []byte
AuctionRound int // Round when the auction bid was submitted
}
ScheduledMessage represents a message whose auction bid has been submitted, awaiting auction resolution and potential transmission.
type ServerMessager ¶
type ServerMessager struct {
Config *ADCNetConfig
ServerID ServerID
}
ServerMessager implements server-side operations for message unblinding.
func ServerSetup ¶
func ServerSetup(config *ADCNetConfig, clientPubkeys map[string]*ecdh.PublicKey, serverId ServerID, serverPrivkey *ecdh.PrivateKey) (*ServerMessager, error)
ServerSetup creates a ServerMessager by deriving shared secrets with all clients.
func (*ServerMessager) UnblindAggregate ¶
func (s *ServerMessager) UnblindAggregate(currentRound int, aggregate *AggregatedClientMessages) (*ServerPartialDecryptionMessage, error)
UnblindAggregate computes this server's blinding vector contribution.
func (*ServerMessager) UnblindPartialMessages ¶
func (s *ServerMessager) UnblindPartialMessages(msgs []*ServerPartialDecryptionMessage) (*RoundBroadcast, error)
UnblindPartialMessages reconstructs the final broadcast by combining blinding vectors.
type ServerPartialDecryptionMessage ¶
type ServerPartialDecryptionMessage struct {
ServerID ServerID
OriginalAggregate *AggregatedClientMessages
UserPKs []crypto.PublicKey
AuctionVector []*big.Int // Server's auction blinding vector
MessageVector []byte // Server's XOR blinding vector
}
ServerPartialDecryptionMessage contains a server's blinding contribution.
type ServerRoundData ¶
type ServerRoundData struct {
Round int
ServerPartialDecryptionMessages map[ServerID]*ServerPartialDecryptionMessage
PartialDecryptionMessage *ServerPartialDecryptionMessage
RoundOutput *RoundBroadcast
}
ServerRoundData holds per-round state for message reconstruction.
type ServerService ¶
type ServerService struct {
// contains filtered or unexported fields
}
ServerService manages server-side protocol operations.
func NewServerService ¶
func NewServerService(config *ADCNetConfig, serverId ServerID, serverSigningKey crypto.PrivateKey, serverExchangeKey *ecdh.PrivateKey) *ServerService
NewServerService creates a server service with the given configuration and keys.
func (*ServerService) AdvanceToRound ¶
func (s *ServerService) AdvanceToRound(round Round)
AdvanceToRound transitions the server to a new protocol round.
func (*ServerService) DeregisterClient ¶
func (s *ServerService) DeregisterClient(clientPubkey crypto.PublicKey) error
DeregisterClient removes a client's shared secret.
func (*ServerService) ProcessAggregateMessage ¶
func (s *ServerService) ProcessAggregateMessage(msg *AggregatedClientMessages) (*ServerPartialDecryptionMessage, error)
ProcessAggregateMessage removes this server's blinding factors from the aggregate.
func (*ServerService) ProcessPartialDecryptionMessage ¶
func (s *ServerService) ProcessPartialDecryptionMessage(msg *ServerPartialDecryptionMessage) (*RoundBroadcast, error)
ProcessPartialDecryptionMessage collects partial decryptions from servers.
func (*ServerService) RegisterClient ¶
func (s *ServerService) RegisterClient(clientPubkey crypto.PublicKey, clientECDHPubkey *ecdh.PublicKey) error
RegisterClient establishes a shared secret with a client via ECDH.
type Signed ¶
type Signed[T any] struct { PublicKey crypto.PublicKey `json:"public_key"` Signature crypto.Signature `json:"signature"` Object *T `json:"object"` }
Signed wraps a message with Ed25519 signature for authentication.
func NewSigned ¶
func NewSigned[T any](privkey crypto.PrivateKey, obj *T) (*Signed[T], error)
NewSigned creates an authenticated message by signing the serialized object and public key.
func (*Signed[T]) Recover ¶
Recover verifies the signature and returns the authenticated object with signer's public key.
func (*Signed[T]) UnsafeObject ¶
func (s *Signed[T]) UnsafeObject() *T
UnsafeObject returns the wrapped object without verifying the signature.
type VerifiedClientMessage ¶
type VerifiedClientMessage struct {
Message *ClientRoundMessage
Signer crypto.PublicKey
}
VerifiedClientMessage contains a pre-verified client message with its signer.
func VerifyClientMessages ¶
func VerifyClientMessages(msgs []*Signed[ClientRoundMessage]) ([]VerifiedClientMessage, error)
VerifyClientMessages verifies signatures on client messages before aggregation. This should be called before acquiring locks to prevent DoS.