Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions willow/proto/willow/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,20 @@ package(
default_visibility = ["//visibility:public"],
)

proto_library(
name = "committee_selector_proto",
srcs = ["committee_selector.proto"],
deps = [
"@protobuf//:any_proto",
"@protobuf//:timestamp_proto",
],
)

cc_proto_library(
name = "committee_selector_cc_proto",
deps = [":committee_selector_proto"],
)

proto_library(
name = "aggregation_config_proto",
srcs = ["aggregation_config.proto"],
Expand Down
208 changes: 208 additions & 0 deletions willow/proto/willow/committee_selector.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
// Copyright 2026 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

syntax = "proto3";

package secure_aggregation.willow;

import "google/protobuf/any.proto";
import "google/protobuf/timestamp.proto";

option java_multiple_files = true;

// Represents a member's status within a specific session or overall.
message MemberStatus {
enum Status {
MEMBER_STATUS_UNKNOWN = 0;
MEMBER_STATUS_PENDING = 1; // Waiting for action/input.
MEMBER_STATUS_ACTIVE = 2; // Actively participating.
MEMBER_STATUS_COMPLETED = 3; // Finished their part.
MEMBER_STATUS_UNRESPONDED = 4; // No response received.
MEMBER_STATUS_FAILED = 5; // Encountered an error.
MEMBER_STATUS_NOT_INVOLVED =
6; // Not part of this specific session/protocol.
}
Status status = 1;

// The method and state of the endorsement of the client’s public key.
enum EndorsementStatus {
ENDORSEMENT_UNKNOWN = 0;
ENDORSEMENT_FAILED = 1;
ENDORSEMENT_ANDROID_KEY_ATTESTATION_VALID = 2;
}
EndorsementStatus key_endorsement_status = 2;

string message = 3; // Optional details on the status.

google.protobuf.Timestamp last_update_time = 4;
}

// Represents a volunteer of a committee.
message Member {
// Unique identifier for the member.
string member_id = 1;

// Member's public key for secure communication.
bytes public_key = 2;

// Token provided to the member for committee access.
string access_token = 3;

// An endorsement of the validity of the public key, e.g.
// an Android Key Attestation X.509 certificate.
google.protobuf.Any key_endorsement = 4;

// Overall status of this member in the context of the committee.
MemberStatus general_status = 5;

// Optional: A specific committee ID the client wishes to join (if known).
string committee_id = 6;
}

// A message sent from client to server signaling intent to
// volunteer for the committee.
message VolunteerForCommitteeRequest {
// Information about the volunteer to join the committee.
string member_id = 1;

// Member's public key for secure communication.
bytes public_key = 2;

// A key endorsement of the client's public key, for example:
// an Android Key Attestation X.509 certificate.
google.protobuf.Any key_endorsement = 3;

// Optional: The committee ID is what the client wishes to join (if known).
string committee_id = 4;
}

message VolunteerForCommitteeResponse {
string member_id = 1;

string committee_id = 2;

// Message for the volunteer, for example:
// "Successfully registered as a volunteer." or
// "Android Key Attestation X.509 verification failed."
string volunteer_message = 3;

// Optional: A token the client uses for subsequent authentication.
// Only populated if the client's key endorsement succeeds.
string access_token = 4;

// An acknowledgement that Google handled the request.
// For example a measurement and endorsement from a TEE.
google.protobuf.Any volunteer_recorded_attestation = 5;

// Optional: Suggest the rate at which clients return to volunteer.
google.protobuf.Any traffic_steering_parameters = 6;
}

// A message passed from Google's untrusted server to
// a TEE to record a batch of committee volunteers.
message VolunteerBatchForCommitteeRequest {
// A batch of volunteers signaling intent to join the cohort.
repeated VolunteerForCommitteeRequest volunteers = 1;
}

message CommitteeAssignment {
// The committee ID the volunteer is assigned to.
string committee_id = 1;

// Message for the volunteer, for example:
// "Successfully registered as a volunteer." or
// "Android Key Attestation X.509 verification failed."
string message = 2;
}

// A response from the TEE to Google's untrusted server
// after recording a batch of committee volunteers.
message VolunteerBatchForCommitteeResponse {
map<string, CommitteeAssignment> committee_assignments = 1;

// An acknowledgement that Google handled the request.
// For example a measurement and endorsement from a TEE.
google.protobuf.Any volunteer_recorded_attestation = 2;

// Optional: Suggest the rate at which clients return to volunteer.
google.protobuf.Any traffic_steering_parameters = 3;
}

// A message passed from Google's untrusted server to
// a TEE to sample a committee from the cohort.
message SampleCommitteeRequest {
string committee_id = 1;
}

// A response from the TEE to Google's untrusted server
// with the output of the committee selection process.
message SampleCommitteeResponse {
string committee_id = 1;

repeated Member committee_members = 2;
}

// Request to check the status of a volunteer.
message CheckVolunteerStatusRequest {
string member_id = 1;

string committee_id = 2;
}

// Response with the status of a volunteer.
message CheckVolunteerStatusResponse {
MemberStatus status = 1;
}

// Request to check the status of a batch of volunteers.
message CheckVolunteerBatchStatusRequest {
repeated string member_ids = 1;

string committee_id = 2;
}

// Response with the status of a batch of volunteers.
message CheckVolunteerBatchStatusResponse {
map<string, MemberStatus> statuses = 1;
}

// Error status.
message CommitteeSelectorStatus {
int32 code = 1;
string message = 2;
}

// CommitteeSelectorRequest and CommitteeSelectorResponse wrap the individual
// request and response messages above, and are used by the replicated
// implementation of the CommitteeSelector.
message CommitteeSelectorRequest {
oneof msg {
VolunteerForCommitteeRequest volunteer_for_committee = 1;
SampleCommitteeRequest sample_committee = 2;
CheckVolunteerStatusRequest check_volunteer_status = 3;
VolunteerBatchForCommitteeRequest volunteer_batch_for_committee = 4;
CheckVolunteerBatchStatusRequest check_volunteer_batch_status = 5;
}
}

message CommitteeSelectorResponse {
oneof msg {
VolunteerForCommitteeResponse volunteer_for_committee = 1;
SampleCommitteeResponse sample_committee = 2;
CheckVolunteerStatusResponse check_volunteer_status = 3;
VolunteerBatchForCommitteeResponse volunteer_batch_for_committee = 4;
CheckVolunteerBatchStatusResponse check_volunteer_batch_status = 5;
CommitteeSelectorStatus error = 6;
}
}