1*14675a02SAndroid Build Coastguard Worker /*
2*14675a02SAndroid Build Coastguard Worker * Copyright 2019 Google LLC
3*14675a02SAndroid Build Coastguard Worker *
4*14675a02SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*14675a02SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*14675a02SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*14675a02SAndroid Build Coastguard Worker *
8*14675a02SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*14675a02SAndroid Build Coastguard Worker *
10*14675a02SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*14675a02SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*14675a02SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*14675a02SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*14675a02SAndroid Build Coastguard Worker * limitations under the License.
15*14675a02SAndroid Build Coastguard Worker */
16*14675a02SAndroid Build Coastguard Worker
17*14675a02SAndroid Build Coastguard Worker #include "fcp/secagg/server/secagg_server.h"
18*14675a02SAndroid Build Coastguard Worker
19*14675a02SAndroid Build Coastguard Worker #include <algorithm>
20*14675a02SAndroid Build Coastguard Worker #include <cstddef>
21*14675a02SAndroid Build Coastguard Worker #include <functional>
22*14675a02SAndroid Build Coastguard Worker #include <memory>
23*14675a02SAndroid Build Coastguard Worker #include <string>
24*14675a02SAndroid Build Coastguard Worker #include <utility>
25*14675a02SAndroid Build Coastguard Worker
26*14675a02SAndroid Build Coastguard Worker #include "absl/container/flat_hash_set.h"
27*14675a02SAndroid Build Coastguard Worker #include "absl/container/node_hash_set.h"
28*14675a02SAndroid Build Coastguard Worker #include "absl/strings/str_cat.h"
29*14675a02SAndroid Build Coastguard Worker #include "fcp/base/monitoring.h"
30*14675a02SAndroid Build Coastguard Worker #include "fcp/secagg/server/aes/aes_secagg_server_protocol_impl.h"
31*14675a02SAndroid Build Coastguard Worker #include "fcp/secagg/server/experiments_names.h"
32*14675a02SAndroid Build Coastguard Worker #include "fcp/secagg/server/graph_parameter_finder.h"
33*14675a02SAndroid Build Coastguard Worker #include "fcp/secagg/server/secagg_scheduler.h"
34*14675a02SAndroid Build Coastguard Worker #include "fcp/secagg/server/secagg_server_aborted_state.h"
35*14675a02SAndroid Build Coastguard Worker #include "fcp/secagg/server/secagg_server_enums.pb.h"
36*14675a02SAndroid Build Coastguard Worker #include "fcp/secagg/server/secagg_server_messages.pb.h"
37*14675a02SAndroid Build Coastguard Worker #include "fcp/secagg/server/secagg_server_metrics_listener.h"
38*14675a02SAndroid Build Coastguard Worker #include "fcp/secagg/server/secagg_server_r0_advertise_keys_state.h"
39*14675a02SAndroid Build Coastguard Worker #include "fcp/secagg/server/secagg_server_state.h"
40*14675a02SAndroid Build Coastguard Worker #include "fcp/secagg/server/secagg_trace_utility.h"
41*14675a02SAndroid Build Coastguard Worker #include "fcp/secagg/server/secret_sharing_graph.h"
42*14675a02SAndroid Build Coastguard Worker #include "fcp/secagg/server/secret_sharing_graph_factory.h"
43*14675a02SAndroid Build Coastguard Worker #include "fcp/secagg/server/send_to_clients_interface.h"
44*14675a02SAndroid Build Coastguard Worker #include "fcp/secagg/server/tracing_schema.h"
45*14675a02SAndroid Build Coastguard Worker #include "fcp/secagg/shared/aes_ctr_prng_factory.h"
46*14675a02SAndroid Build Coastguard Worker #include "fcp/secagg/shared/aes_prng_factory.h"
47*14675a02SAndroid Build Coastguard Worker #include "fcp/secagg/shared/input_vector_specification.h"
48*14675a02SAndroid Build Coastguard Worker #include "fcp/secagg/shared/secagg_messages.pb.h"
49*14675a02SAndroid Build Coastguard Worker #include "fcp/tracing/tracing_span.h"
50*14675a02SAndroid Build Coastguard Worker
51*14675a02SAndroid Build Coastguard Worker namespace fcp {
52*14675a02SAndroid Build Coastguard Worker namespace secagg {
53*14675a02SAndroid Build Coastguard Worker
SecAggServer(std::unique_ptr<SecAggServerProtocolImpl> impl)54*14675a02SAndroid Build Coastguard Worker SecAggServer::SecAggServer(std::unique_ptr<SecAggServerProtocolImpl> impl) {
55*14675a02SAndroid Build Coastguard Worker state_ = std::make_unique<SecAggServerR0AdvertiseKeysState>(std::move(impl));
56*14675a02SAndroid Build Coastguard Worker
57*14675a02SAndroid Build Coastguard Worker // Start the span for the current state. The rest of the state span
58*14675a02SAndroid Build Coastguard Worker // transitioning is done in TransitionState.
59*14675a02SAndroid Build Coastguard Worker state_span_ = std::make_unique<UnscopedTracingSpan<SecureAggServerState>>(
60*14675a02SAndroid Build Coastguard Worker span_.Ref(), TracingState(state_->State()));
61*14675a02SAndroid Build Coastguard Worker }
62*14675a02SAndroid Build Coastguard Worker
Create(int minimum_number_of_clients_to_proceed,int total_number_of_clients,const std::vector<InputVectorSpecification> & input_vector_specs,SendToClientsInterface * sender,std::unique_ptr<SecAggServerMetricsListener> metrics,std::unique_ptr<SecAggScheduler> prng_runner,std::unique_ptr<ExperimentsInterface> experiments,const SecureAggregationRequirements & threat_model)63*14675a02SAndroid Build Coastguard Worker StatusOr<std::unique_ptr<SecAggServer>> SecAggServer::Create(
64*14675a02SAndroid Build Coastguard Worker int minimum_number_of_clients_to_proceed, int total_number_of_clients,
65*14675a02SAndroid Build Coastguard Worker const std::vector<InputVectorSpecification>& input_vector_specs,
66*14675a02SAndroid Build Coastguard Worker SendToClientsInterface* sender,
67*14675a02SAndroid Build Coastguard Worker std::unique_ptr<SecAggServerMetricsListener> metrics,
68*14675a02SAndroid Build Coastguard Worker std::unique_ptr<SecAggScheduler> prng_runner,
69*14675a02SAndroid Build Coastguard Worker std::unique_ptr<ExperimentsInterface> experiments,
70*14675a02SAndroid Build Coastguard Worker const SecureAggregationRequirements& threat_model) {
71*14675a02SAndroid Build Coastguard Worker TracingSpan<CreateSecAggServer> span;
72*14675a02SAndroid Build Coastguard Worker SecretSharingGraphFactory factory;
73*14675a02SAndroid Build Coastguard Worker std::unique_ptr<SecretSharingGraph> secret_sharing_graph;
74*14675a02SAndroid Build Coastguard Worker ServerVariant server_variant = ServerVariant::UNKNOWN_VERSION;
75*14675a02SAndroid Build Coastguard Worker
76*14675a02SAndroid Build Coastguard Worker bool is_fullgraph_protocol_variant =
77*14675a02SAndroid Build Coastguard Worker experiments->IsEnabled(kFullgraphSecAggExperiment);
78*14675a02SAndroid Build Coastguard Worker int degree, threshold;
79*14675a02SAndroid Build Coastguard Worker // We first compute parameters degree and threshold for the subgraph variant,
80*14675a02SAndroid Build Coastguard Worker // unless the kFullgraphSecAggExperiment is enabled, and then set
81*14675a02SAndroid Build Coastguard Worker // is_subgraph_protocol_variant to false if the parameter finding procedure
82*14675a02SAndroid Build Coastguard Worker // fails. In that case we resort to classical full-graph secagg.
83*14675a02SAndroid Build Coastguard Worker // This will happen for very small values of total_number_of_clients (e.g. <
84*14675a02SAndroid Build Coastguard Worker // 65), i.e. cohort sizes where subgraph-secagg does not give much advantage.
85*14675a02SAndroid Build Coastguard Worker if (!is_fullgraph_protocol_variant) {
86*14675a02SAndroid Build Coastguard Worker if (experiments->IsEnabled(kForceSubgraphSecAggExperiment)) {
87*14675a02SAndroid Build Coastguard Worker // In kForceSubgraphSecAggExperiment (which is only for testing
88*14675a02SAndroid Build Coastguard Worker // purposes) we fix the degree in the Harary graph to be half the number
89*14675a02SAndroid Build Coastguard Worker // of clients (rounding to the next odd number to account for self-edges
90*14675a02SAndroid Build Coastguard Worker // as above) and degree to be half of the degree (or 2 whatever is
91*14675a02SAndroid Build Coastguard Worker // larger). This means that, for example in a simple test with 5
92*14675a02SAndroid Build Coastguard Worker // clients, each client shares keys with 2 other clients and the
93*14675a02SAndroid Build Coastguard Worker // threshold is one.
94*14675a02SAndroid Build Coastguard Worker degree = total_number_of_clients / 2;
95*14675a02SAndroid Build Coastguard Worker if (degree % 2 == 0) {
96*14675a02SAndroid Build Coastguard Worker degree += 1;
97*14675a02SAndroid Build Coastguard Worker }
98*14675a02SAndroid Build Coastguard Worker threshold = std::max(2, degree / 2);
99*14675a02SAndroid Build Coastguard Worker
100*14675a02SAndroid Build Coastguard Worker } else {
101*14675a02SAndroid Build Coastguard Worker // kSubgraphSecAggCuriousServerExperiment sets the threat model to
102*14675a02SAndroid Build Coastguard Worker // CURIOUS_SERVER in subgraph-secagg executions.
103*14675a02SAndroid Build Coastguard Worker // This experiment was introduced as part of go/subgraph-secagg-rollout
104*14675a02SAndroid Build Coastguard Worker // and is temporary (see b/191179307).
105*14675a02SAndroid Build Coastguard Worker StatusOr<fcp::secagg::HararyGraphParameters>
106*14675a02SAndroid Build Coastguard Worker computed_params_status_or_value;
107*14675a02SAndroid Build Coastguard Worker if (experiments->IsEnabled(kSubgraphSecAggCuriousServerExperiment)) {
108*14675a02SAndroid Build Coastguard Worker SecureAggregationRequirements alternate_threat_model = threat_model;
109*14675a02SAndroid Build Coastguard Worker alternate_threat_model.set_adversary_class(
110*14675a02SAndroid Build Coastguard Worker AdversaryClass::CURIOUS_SERVER);
111*14675a02SAndroid Build Coastguard Worker computed_params_status_or_value = ComputeHararyGraphParameters(
112*14675a02SAndroid Build Coastguard Worker total_number_of_clients, alternate_threat_model);
113*14675a02SAndroid Build Coastguard Worker } else {
114*14675a02SAndroid Build Coastguard Worker computed_params_status_or_value =
115*14675a02SAndroid Build Coastguard Worker ComputeHararyGraphParameters(total_number_of_clients, threat_model);
116*14675a02SAndroid Build Coastguard Worker }
117*14675a02SAndroid Build Coastguard Worker if (computed_params_status_or_value.ok()) {
118*14675a02SAndroid Build Coastguard Worker // We add 1 to the computed degree to account for a self-edge in the
119*14675a02SAndroid Build Coastguard Worker // SecretSharingHararyGraph graph
120*14675a02SAndroid Build Coastguard Worker degree = computed_params_status_or_value->degree + 1;
121*14675a02SAndroid Build Coastguard Worker threshold = computed_params_status_or_value->threshold;
122*14675a02SAndroid Build Coastguard Worker } else {
123*14675a02SAndroid Build Coastguard Worker is_fullgraph_protocol_variant = true;
124*14675a02SAndroid Build Coastguard Worker }
125*14675a02SAndroid Build Coastguard Worker }
126*14675a02SAndroid Build Coastguard Worker }
127*14675a02SAndroid Build Coastguard Worker
128*14675a02SAndroid Build Coastguard Worker // In both the FullGraph and SubGraph variants, the protocol only successfully
129*14675a02SAndroid Build Coastguard Worker // completes and returns a sum if no more than
130*14675a02SAndroid Build Coastguard Worker // floor(total_number_of_clients * threat_model.estimated_dropout_rate())
131*14675a02SAndroid Build Coastguard Worker // clients dropout before the end of the protocol execution. This ensure that
132*14675a02SAndroid Build Coastguard Worker // at least ceil(total_number_of_clients *(1. -
133*14675a02SAndroid Build Coastguard Worker // threat_model.estimated_dropout_rate() -
134*14675a02SAndroid Build Coastguard Worker // threat_model.adversarial_client_rate)) values from honest clients are
135*14675a02SAndroid Build Coastguard Worker // included in the final sum.
136*14675a02SAndroid Build Coastguard Worker // The protocol allows to make that threshold larger by providing a larger
137*14675a02SAndroid Build Coastguard Worker // value of minimum_number_of_clients_to_proceed to the create function, but
138*14675a02SAndroid Build Coastguard Worker // never lower.
139*14675a02SAndroid Build Coastguard Worker minimum_number_of_clients_to_proceed =
140*14675a02SAndroid Build Coastguard Worker std::max(minimum_number_of_clients_to_proceed,
141*14675a02SAndroid Build Coastguard Worker static_cast<int>(
142*14675a02SAndroid Build Coastguard Worker std::ceil(total_number_of_clients *
143*14675a02SAndroid Build Coastguard Worker (1. - threat_model.estimated_dropout_rate()))));
144*14675a02SAndroid Build Coastguard Worker if (is_fullgraph_protocol_variant) {
145*14675a02SAndroid Build Coastguard Worker // We're instantiating full-graph secagg, either because that was
146*14675a02SAndroid Build Coastguard Worker // the intent of the caller (by setting kFullgraphSecAggExperiment), or
147*14675a02SAndroid Build Coastguard Worker // because ComputeHararyGraphParameters returned and error.
148*14675a02SAndroid Build Coastguard Worker FCP_RETURN_IF_ERROR(CheckFullGraphParameters(
149*14675a02SAndroid Build Coastguard Worker total_number_of_clients, minimum_number_of_clients_to_proceed,
150*14675a02SAndroid Build Coastguard Worker threat_model));
151*14675a02SAndroid Build Coastguard Worker secret_sharing_graph = factory.CreateCompleteGraph(
152*14675a02SAndroid Build Coastguard Worker total_number_of_clients, minimum_number_of_clients_to_proceed);
153*14675a02SAndroid Build Coastguard Worker server_variant = ServerVariant::NATIVE_V1;
154*14675a02SAndroid Build Coastguard Worker Trace<FullGraphServerParameters>(
155*14675a02SAndroid Build Coastguard Worker total_number_of_clients, minimum_number_of_clients_to_proceed,
156*14675a02SAndroid Build Coastguard Worker experiments->IsEnabled(kSecAggAsyncRound2Experiment));
157*14675a02SAndroid Build Coastguard Worker } else {
158*14675a02SAndroid Build Coastguard Worker secret_sharing_graph =
159*14675a02SAndroid Build Coastguard Worker factory.CreateHararyGraph(total_number_of_clients, degree, threshold);
160*14675a02SAndroid Build Coastguard Worker server_variant = ServerVariant::NATIVE_SUBGRAPH;
161*14675a02SAndroid Build Coastguard Worker Trace<SubGraphServerParameters>(
162*14675a02SAndroid Build Coastguard Worker total_number_of_clients, degree, threshold,
163*14675a02SAndroid Build Coastguard Worker minimum_number_of_clients_to_proceed,
164*14675a02SAndroid Build Coastguard Worker experiments->IsEnabled(kSecAggAsyncRound2Experiment));
165*14675a02SAndroid Build Coastguard Worker }
166*14675a02SAndroid Build Coastguard Worker
167*14675a02SAndroid Build Coastguard Worker return absl::WrapUnique(
168*14675a02SAndroid Build Coastguard Worker new SecAggServer(std::make_unique<AesSecAggServerProtocolImpl>(
169*14675a02SAndroid Build Coastguard Worker std::move(secret_sharing_graph), minimum_number_of_clients_to_proceed,
170*14675a02SAndroid Build Coastguard Worker input_vector_specs, std::move(metrics),
171*14675a02SAndroid Build Coastguard Worker std::make_unique<AesCtrPrngFactory>(), sender, std::move(prng_runner),
172*14675a02SAndroid Build Coastguard Worker std::vector<ClientStatus>(total_number_of_clients,
173*14675a02SAndroid Build Coastguard Worker ClientStatus::READY_TO_START),
174*14675a02SAndroid Build Coastguard Worker server_variant, std::move(experiments))));
175*14675a02SAndroid Build Coastguard Worker }
176*14675a02SAndroid Build Coastguard Worker
Abort()177*14675a02SAndroid Build Coastguard Worker Status SecAggServer::Abort() {
178*14675a02SAndroid Build Coastguard Worker const std::string reason = "Abort upon external request.";
179*14675a02SAndroid Build Coastguard Worker TracingSpan<AbortSecAggServer> span(state_span_->Ref(), reason);
180*14675a02SAndroid Build Coastguard Worker FCP_RETURN_IF_ERROR(ErrorIfAbortedOrCompleted());
181*14675a02SAndroid Build Coastguard Worker TransitionState(state_->Abort(reason, SecAggServerOutcome::EXTERNAL_REQUEST));
182*14675a02SAndroid Build Coastguard Worker return FCP_STATUS(OK);
183*14675a02SAndroid Build Coastguard Worker }
184*14675a02SAndroid Build Coastguard Worker
Abort(const std::string & reason,SecAggServerOutcome outcome)185*14675a02SAndroid Build Coastguard Worker Status SecAggServer::Abort(const std::string& reason,
186*14675a02SAndroid Build Coastguard Worker SecAggServerOutcome outcome) {
187*14675a02SAndroid Build Coastguard Worker const std::string formatted_reason =
188*14675a02SAndroid Build Coastguard Worker absl::StrCat("Abort upon external request for reason <", reason, ">.");
189*14675a02SAndroid Build Coastguard Worker TracingSpan<AbortSecAggServer> span(state_span_->Ref(), formatted_reason);
190*14675a02SAndroid Build Coastguard Worker FCP_RETURN_IF_ERROR(ErrorIfAbortedOrCompleted());
191*14675a02SAndroid Build Coastguard Worker TransitionState(state_->Abort(formatted_reason, outcome));
192*14675a02SAndroid Build Coastguard Worker return FCP_STATUS(OK);
193*14675a02SAndroid Build Coastguard Worker }
194*14675a02SAndroid Build Coastguard Worker
MakeClientAbortMessage(ClientAbortReason reason)195*14675a02SAndroid Build Coastguard Worker std::string MakeClientAbortMessage(ClientAbortReason reason) {
196*14675a02SAndroid Build Coastguard Worker return absl::StrCat("The protocol is closing client with ClientAbortReason <",
197*14675a02SAndroid Build Coastguard Worker ClientAbortReason_Name(reason), ">.");
198*14675a02SAndroid Build Coastguard Worker }
199*14675a02SAndroid Build Coastguard Worker
AbortClient(uint32_t client_id,ClientAbortReason reason)200*14675a02SAndroid Build Coastguard Worker Status SecAggServer::AbortClient(uint32_t client_id, ClientAbortReason reason) {
201*14675a02SAndroid Build Coastguard Worker TracingSpan<AbortSecAggClient> span(
202*14675a02SAndroid Build Coastguard Worker state_span_->Ref(), client_id,
203*14675a02SAndroid Build Coastguard Worker ClientAbortReason_descriptor()->FindValueByNumber(reason)->name());
204*14675a02SAndroid Build Coastguard Worker FCP_RETURN_IF_ERROR(ErrorIfAbortedOrCompleted());
205*14675a02SAndroid Build Coastguard Worker FCP_RETURN_IF_ERROR(ValidateClientId(client_id));
206*14675a02SAndroid Build Coastguard Worker // By default, put all AbortClient calls in the same bucket (with some
207*14675a02SAndroid Build Coastguard Worker // exceptions below).
208*14675a02SAndroid Build Coastguard Worker ClientDropReason client_drop_reason =
209*14675a02SAndroid Build Coastguard Worker ClientDropReason::SERVER_PROTOCOL_ABORT_CLIENT;
210*14675a02SAndroid Build Coastguard Worker bool notify_client = false;
211*14675a02SAndroid Build Coastguard Worker bool log_metrics = true;
212*14675a02SAndroid Build Coastguard Worker std::string message;
213*14675a02SAndroid Build Coastguard Worker // Handle all specific abortClient cases
214*14675a02SAndroid Build Coastguard Worker switch (reason) {
215*14675a02SAndroid Build Coastguard Worker case ClientAbortReason::INVALID_MESSAGE:
216*14675a02SAndroid Build Coastguard Worker notify_client = true;
217*14675a02SAndroid Build Coastguard Worker message = MakeClientAbortMessage(reason);
218*14675a02SAndroid Build Coastguard Worker break;
219*14675a02SAndroid Build Coastguard Worker case ClientAbortReason::CONNECTION_DROPPED:
220*14675a02SAndroid Build Coastguard Worker client_drop_reason = ClientDropReason::CONNECTION_CLOSED;
221*14675a02SAndroid Build Coastguard Worker break;
222*14675a02SAndroid Build Coastguard Worker default:
223*14675a02SAndroid Build Coastguard Worker log_metrics = false;
224*14675a02SAndroid Build Coastguard Worker message = MakeClientAbortMessage(reason);
225*14675a02SAndroid Build Coastguard Worker break;
226*14675a02SAndroid Build Coastguard Worker }
227*14675a02SAndroid Build Coastguard Worker
228*14675a02SAndroid Build Coastguard Worker state_->AbortClient(client_id, message, client_drop_reason, notify_client,
229*14675a02SAndroid Build Coastguard Worker log_metrics);
230*14675a02SAndroid Build Coastguard Worker return FCP_STATUS(OK);
231*14675a02SAndroid Build Coastguard Worker }
232*14675a02SAndroid Build Coastguard Worker
ProceedToNextRound()233*14675a02SAndroid Build Coastguard Worker Status SecAggServer::ProceedToNextRound() {
234*14675a02SAndroid Build Coastguard Worker TracingSpan<ProceedToNextSecAggRound> span(state_span_->Ref());
235*14675a02SAndroid Build Coastguard Worker FCP_RETURN_IF_ERROR(ErrorIfAbortedOrCompleted());
236*14675a02SAndroid Build Coastguard Worker StatusOr<std::unique_ptr<SecAggServerState>> status_or_next_state =
237*14675a02SAndroid Build Coastguard Worker state_->ProceedToNextRound();
238*14675a02SAndroid Build Coastguard Worker if (status_or_next_state.ok()) {
239*14675a02SAndroid Build Coastguard Worker TransitionState(std::move(status_or_next_state.value()));
240*14675a02SAndroid Build Coastguard Worker }
241*14675a02SAndroid Build Coastguard Worker return status_or_next_state.status();
242*14675a02SAndroid Build Coastguard Worker }
243*14675a02SAndroid Build Coastguard Worker
ReceiveMessage(uint32_t client_id,std::unique_ptr<ClientToServerWrapperMessage> message)244*14675a02SAndroid Build Coastguard Worker StatusOr<bool> SecAggServer::ReceiveMessage(
245*14675a02SAndroid Build Coastguard Worker uint32_t client_id, std::unique_ptr<ClientToServerWrapperMessage> message) {
246*14675a02SAndroid Build Coastguard Worker TracingSpan<ReceiveSecAggMessage> span(state_span_->Ref(), client_id);
247*14675a02SAndroid Build Coastguard Worker FCP_RETURN_IF_ERROR(ErrorIfAbortedOrCompleted());
248*14675a02SAndroid Build Coastguard Worker FCP_RETURN_IF_ERROR(ValidateClientId(client_id));
249*14675a02SAndroid Build Coastguard Worker FCP_RETURN_IF_ERROR(state_->HandleMessage(client_id, std::move(message)));
250*14675a02SAndroid Build Coastguard Worker return ReadyForNextRound();
251*14675a02SAndroid Build Coastguard Worker }
252*14675a02SAndroid Build Coastguard Worker
SetAsyncCallback(std::function<void ()> async_callback)253*14675a02SAndroid Build Coastguard Worker bool SecAggServer::SetAsyncCallback(std::function<void()> async_callback) {
254*14675a02SAndroid Build Coastguard Worker return state_->SetAsyncCallback(async_callback);
255*14675a02SAndroid Build Coastguard Worker }
256*14675a02SAndroid Build Coastguard Worker
TransitionState(std::unique_ptr<SecAggServerState> new_state)257*14675a02SAndroid Build Coastguard Worker void SecAggServer::TransitionState(
258*14675a02SAndroid Build Coastguard Worker std::unique_ptr<SecAggServerState> new_state) {
259*14675a02SAndroid Build Coastguard Worker // Reset state_span_ before creating a new unscoped span for the next state
260*14675a02SAndroid Build Coastguard Worker // to ensure old span is destructed before the new one is created.
261*14675a02SAndroid Build Coastguard Worker state_span_.reset();
262*14675a02SAndroid Build Coastguard Worker state_ = std::move(new_state);
263*14675a02SAndroid Build Coastguard Worker state_span_ = std::make_unique<UnscopedTracingSpan<SecureAggServerState>>(
264*14675a02SAndroid Build Coastguard Worker span_.Ref(), TracingState(state_->State()));
265*14675a02SAndroid Build Coastguard Worker state_->EnterState();
266*14675a02SAndroid Build Coastguard Worker }
267*14675a02SAndroid Build Coastguard Worker
AbortedClientIds() const268*14675a02SAndroid Build Coastguard Worker absl::flat_hash_set<uint32_t> SecAggServer::AbortedClientIds() const {
269*14675a02SAndroid Build Coastguard Worker return state_->AbortedClientIds();
270*14675a02SAndroid Build Coastguard Worker }
271*14675a02SAndroid Build Coastguard Worker
ErrorMessage() const272*14675a02SAndroid Build Coastguard Worker StatusOr<std::string> SecAggServer::ErrorMessage() const {
273*14675a02SAndroid Build Coastguard Worker return state_->ErrorMessage();
274*14675a02SAndroid Build Coastguard Worker }
275*14675a02SAndroid Build Coastguard Worker
IsAborted() const276*14675a02SAndroid Build Coastguard Worker bool SecAggServer::IsAborted() const { return state_->IsAborted(); }
277*14675a02SAndroid Build Coastguard Worker
IsCompletedSuccessfully() const278*14675a02SAndroid Build Coastguard Worker bool SecAggServer::IsCompletedSuccessfully() const {
279*14675a02SAndroid Build Coastguard Worker return state_->IsCompletedSuccessfully();
280*14675a02SAndroid Build Coastguard Worker }
281*14675a02SAndroid Build Coastguard Worker
IsNumberOfIncludedInputsCommitted() const282*14675a02SAndroid Build Coastguard Worker bool SecAggServer::IsNumberOfIncludedInputsCommitted() const {
283*14675a02SAndroid Build Coastguard Worker return state_->IsNumberOfIncludedInputsCommitted();
284*14675a02SAndroid Build Coastguard Worker }
285*14675a02SAndroid Build Coastguard Worker
MinimumMessagesNeededForNextRound() const286*14675a02SAndroid Build Coastguard Worker StatusOr<int> SecAggServer::MinimumMessagesNeededForNextRound() const {
287*14675a02SAndroid Build Coastguard Worker FCP_RETURN_IF_ERROR(ErrorIfAbortedOrCompleted());
288*14675a02SAndroid Build Coastguard Worker return state_->MinimumMessagesNeededForNextRound();
289*14675a02SAndroid Build Coastguard Worker }
290*14675a02SAndroid Build Coastguard Worker
NumberOfAliveClients() const291*14675a02SAndroid Build Coastguard Worker int SecAggServer::NumberOfAliveClients() const {
292*14675a02SAndroid Build Coastguard Worker return state_->NumberOfAliveClients();
293*14675a02SAndroid Build Coastguard Worker }
294*14675a02SAndroid Build Coastguard Worker
NumberOfClientsFailedAfterSendingMaskedInput() const295*14675a02SAndroid Build Coastguard Worker int SecAggServer::NumberOfClientsFailedAfterSendingMaskedInput() const {
296*14675a02SAndroid Build Coastguard Worker return state_->NumberOfClientsFailedAfterSendingMaskedInput();
297*14675a02SAndroid Build Coastguard Worker }
298*14675a02SAndroid Build Coastguard Worker
NumberOfClientsFailedBeforeSendingMaskedInput() const299*14675a02SAndroid Build Coastguard Worker int SecAggServer::NumberOfClientsFailedBeforeSendingMaskedInput() const {
300*14675a02SAndroid Build Coastguard Worker return state_->NumberOfClientsFailedBeforeSendingMaskedInput();
301*14675a02SAndroid Build Coastguard Worker }
302*14675a02SAndroid Build Coastguard Worker
NumberOfClientsTerminatedWithoutUnmasking() const303*14675a02SAndroid Build Coastguard Worker int SecAggServer::NumberOfClientsTerminatedWithoutUnmasking() const {
304*14675a02SAndroid Build Coastguard Worker return state_->NumberOfClientsTerminatedWithoutUnmasking();
305*14675a02SAndroid Build Coastguard Worker }
306*14675a02SAndroid Build Coastguard Worker
NumberOfIncludedInputs() const307*14675a02SAndroid Build Coastguard Worker int SecAggServer::NumberOfIncludedInputs() const {
308*14675a02SAndroid Build Coastguard Worker return state_->NumberOfIncludedInputs();
309*14675a02SAndroid Build Coastguard Worker }
310*14675a02SAndroid Build Coastguard Worker
NumberOfPendingClients() const311*14675a02SAndroid Build Coastguard Worker int SecAggServer::NumberOfPendingClients() const {
312*14675a02SAndroid Build Coastguard Worker return state_->NumberOfPendingClients();
313*14675a02SAndroid Build Coastguard Worker }
314*14675a02SAndroid Build Coastguard Worker
NumberOfClientsReadyForNextRound() const315*14675a02SAndroid Build Coastguard Worker StatusOr<int> SecAggServer::NumberOfClientsReadyForNextRound() const {
316*14675a02SAndroid Build Coastguard Worker FCP_RETURN_IF_ERROR(ErrorIfAbortedOrCompleted());
317*14675a02SAndroid Build Coastguard Worker return state_->NumberOfClientsReadyForNextRound();
318*14675a02SAndroid Build Coastguard Worker }
319*14675a02SAndroid Build Coastguard Worker
NumberOfMessagesReceivedInThisRound() const320*14675a02SAndroid Build Coastguard Worker StatusOr<int> SecAggServer::NumberOfMessagesReceivedInThisRound() const {
321*14675a02SAndroid Build Coastguard Worker FCP_RETURN_IF_ERROR(ErrorIfAbortedOrCompleted());
322*14675a02SAndroid Build Coastguard Worker return state_->NumberOfMessagesReceivedInThisRound();
323*14675a02SAndroid Build Coastguard Worker }
324*14675a02SAndroid Build Coastguard Worker
ReadyForNextRound() const325*14675a02SAndroid Build Coastguard Worker StatusOr<bool> SecAggServer::ReadyForNextRound() const {
326*14675a02SAndroid Build Coastguard Worker FCP_RETURN_IF_ERROR(ErrorIfAbortedOrCompleted());
327*14675a02SAndroid Build Coastguard Worker return state_->ReadyForNextRound();
328*14675a02SAndroid Build Coastguard Worker }
329*14675a02SAndroid Build Coastguard Worker
Result()330*14675a02SAndroid Build Coastguard Worker StatusOr<std::unique_ptr<SecAggVectorMap>> SecAggServer::Result() {
331*14675a02SAndroid Build Coastguard Worker return state_->Result();
332*14675a02SAndroid Build Coastguard Worker }
333*14675a02SAndroid Build Coastguard Worker
NumberOfNeighbors() const334*14675a02SAndroid Build Coastguard Worker int SecAggServer::NumberOfNeighbors() const {
335*14675a02SAndroid Build Coastguard Worker return state_->number_of_neighbors();
336*14675a02SAndroid Build Coastguard Worker }
337*14675a02SAndroid Build Coastguard Worker
MinimumSurvivingNeighborsForReconstruction() const338*14675a02SAndroid Build Coastguard Worker int SecAggServer::MinimumSurvivingNeighborsForReconstruction() const {
339*14675a02SAndroid Build Coastguard Worker return state_->minimum_surviving_neighbors_for_reconstruction();
340*14675a02SAndroid Build Coastguard Worker }
341*14675a02SAndroid Build Coastguard Worker
State() const342*14675a02SAndroid Build Coastguard Worker SecAggServerStateKind SecAggServer::State() const { return state_->State(); }
343*14675a02SAndroid Build Coastguard Worker
ValidateClientId(uint32_t client_id) const344*14675a02SAndroid Build Coastguard Worker Status SecAggServer::ValidateClientId(uint32_t client_id) const {
345*14675a02SAndroid Build Coastguard Worker if (client_id >= state_->total_number_of_clients()) {
346*14675a02SAndroid Build Coastguard Worker return FCP_STATUS(FAILED_PRECONDITION)
347*14675a02SAndroid Build Coastguard Worker << "Client Id " << client_id
348*14675a02SAndroid Build Coastguard Worker << " is outside of the expected bounds - 0 to "
349*14675a02SAndroid Build Coastguard Worker << state_->total_number_of_clients();
350*14675a02SAndroid Build Coastguard Worker }
351*14675a02SAndroid Build Coastguard Worker return FCP_STATUS(OK);
352*14675a02SAndroid Build Coastguard Worker }
353*14675a02SAndroid Build Coastguard Worker
ErrorIfAbortedOrCompleted() const354*14675a02SAndroid Build Coastguard Worker Status SecAggServer::ErrorIfAbortedOrCompleted() const {
355*14675a02SAndroid Build Coastguard Worker if (state_->IsAborted()) {
356*14675a02SAndroid Build Coastguard Worker return FCP_STATUS(FAILED_PRECONDITION)
357*14675a02SAndroid Build Coastguard Worker << "The server has already aborted. The request cannot be "
358*14675a02SAndroid Build Coastguard Worker "satisfied.";
359*14675a02SAndroid Build Coastguard Worker }
360*14675a02SAndroid Build Coastguard Worker if (state_->IsCompletedSuccessfully()) {
361*14675a02SAndroid Build Coastguard Worker return FCP_STATUS(FAILED_PRECONDITION)
362*14675a02SAndroid Build Coastguard Worker << "The server has already completed the protocol. "
363*14675a02SAndroid Build Coastguard Worker << "Call getOutput() to retrieve the output.";
364*14675a02SAndroid Build Coastguard Worker }
365*14675a02SAndroid Build Coastguard Worker return FCP_STATUS(OK);
366*14675a02SAndroid Build Coastguard Worker }
367*14675a02SAndroid Build Coastguard Worker
368*14675a02SAndroid Build Coastguard Worker } // namespace secagg
369*14675a02SAndroid Build Coastguard Worker } // namespace fcp
370