1*14675a02SAndroid Build Coastguard Worker /* 2*14675a02SAndroid Build Coastguard Worker * Copyright 2020 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 #ifndef FCP_CLIENT_FEDERATED_PROTOCOL_H_ 17*14675a02SAndroid Build Coastguard Worker #define FCP_CLIENT_FEDERATED_PROTOCOL_H_ 18*14675a02SAndroid Build Coastguard Worker 19*14675a02SAndroid Build Coastguard Worker #include <cstdint> 20*14675a02SAndroid Build Coastguard Worker #include <functional> 21*14675a02SAndroid Build Coastguard Worker #include <memory> 22*14675a02SAndroid Build Coastguard Worker #include <optional> 23*14675a02SAndroid Build Coastguard Worker #include <string> 24*14675a02SAndroid Build Coastguard Worker #include <utility> 25*14675a02SAndroid Build Coastguard Worker #include <variant> 26*14675a02SAndroid Build Coastguard Worker #include <vector> 27*14675a02SAndroid Build Coastguard Worker 28*14675a02SAndroid Build Coastguard Worker #include "absl/container/node_hash_map.h" 29*14675a02SAndroid Build Coastguard Worker #include "absl/status/status.h" 30*14675a02SAndroid Build Coastguard Worker #include "absl/status/statusor.h" 31*14675a02SAndroid Build Coastguard Worker #include "fcp/client/engine/engine.pb.h" 32*14675a02SAndroid Build Coastguard Worker #include "fcp/client/stats.h" 33*14675a02SAndroid Build Coastguard Worker #include "fcp/protos/federated_api.pb.h" 34*14675a02SAndroid Build Coastguard Worker #include "fcp/protos/federatedcompute/eligibility_eval_tasks.pb.h" 35*14675a02SAndroid Build Coastguard Worker #include "fcp/protos/plan.pb.h" 36*14675a02SAndroid Build Coastguard Worker 37*14675a02SAndroid Build Coastguard Worker namespace fcp { 38*14675a02SAndroid Build Coastguard Worker namespace client { 39*14675a02SAndroid Build Coastguard Worker 40*14675a02SAndroid Build Coastguard Worker // Data type used to encode results of a computation - a TensorFlow 41*14675a02SAndroid Build Coastguard Worker // checkpoint, or SecAgg quantized tensors. 42*14675a02SAndroid Build Coastguard Worker // For non-SecAgg use (simple federated aggregation, or local computation), 43*14675a02SAndroid Build Coastguard Worker // this map should only contain one entry - a TFCheckpoint - and the string 44*14675a02SAndroid Build Coastguard Worker // should be ignored by downstream code. 45*14675a02SAndroid Build Coastguard Worker // For SecAgg use, there should be 46*14675a02SAndroid Build Coastguard Worker // * at most one TFCheckpoint - again, the key should be ignored - and 47*14675a02SAndroid Build Coastguard Worker // * N QuantizedTensors, whose string keys must map to the tensor names 48*14675a02SAndroid Build Coastguard Worker // provided in the server's CheckinResponse's SideChannelExecutionInfo. 49*14675a02SAndroid Build Coastguard Worker using TFCheckpoint = std::string; 50*14675a02SAndroid Build Coastguard Worker struct QuantizedTensor { 51*14675a02SAndroid Build Coastguard Worker std::vector<uint64_t> values; 52*14675a02SAndroid Build Coastguard Worker int32_t bitwidth = 0; 53*14675a02SAndroid Build Coastguard Worker std::vector<int64_t> dimensions; 54*14675a02SAndroid Build Coastguard Worker 55*14675a02SAndroid Build Coastguard Worker QuantizedTensor() = default; 56*14675a02SAndroid Build Coastguard Worker // Disallow copy and assign. 57*14675a02SAndroid Build Coastguard Worker QuantizedTensor(const QuantizedTensor&) = delete; 58*14675a02SAndroid Build Coastguard Worker QuantizedTensor& operator=(const QuantizedTensor&) = delete; 59*14675a02SAndroid Build Coastguard Worker // Enable move semantics. 60*14675a02SAndroid Build Coastguard Worker QuantizedTensor(QuantizedTensor&&) = default; 61*14675a02SAndroid Build Coastguard Worker QuantizedTensor& operator=(QuantizedTensor&&) = default; 62*14675a02SAndroid Build Coastguard Worker }; 63*14675a02SAndroid Build Coastguard Worker // This is equivalent to using ComputationResults = 64*14675a02SAndroid Build Coastguard Worker // std::map<std::string, std::variant<TFCheckpoint, QuantizedTensor>>; 65*14675a02SAndroid Build Coastguard Worker // except copy construction and assignment are explicitly prohibited and move 66*14675a02SAndroid Build Coastguard Worker // semantics is enforced. 67*14675a02SAndroid Build Coastguard Worker class ComputationResults 68*14675a02SAndroid Build Coastguard Worker : public absl::node_hash_map<std::string, 69*14675a02SAndroid Build Coastguard Worker std::variant<TFCheckpoint, QuantizedTensor>> { 70*14675a02SAndroid Build Coastguard Worker public: 71*14675a02SAndroid Build Coastguard Worker using Base = absl::node_hash_map<std::string, 72*14675a02SAndroid Build Coastguard Worker std::variant<TFCheckpoint, QuantizedTensor>>; 73*14675a02SAndroid Build Coastguard Worker using Base::Base; 74*14675a02SAndroid Build Coastguard Worker using Base::operator=; 75*14675a02SAndroid Build Coastguard Worker ComputationResults(const ComputationResults&) = delete; 76*14675a02SAndroid Build Coastguard Worker ComputationResults& operator=(const ComputationResults&) = delete; 77*14675a02SAndroid Build Coastguard Worker ComputationResults(ComputationResults&&) = default; 78*14675a02SAndroid Build Coastguard Worker ComputationResults& operator=(ComputationResults&&) = default; 79*14675a02SAndroid Build Coastguard Worker }; 80*14675a02SAndroid Build Coastguard Worker 81*14675a02SAndroid Build Coastguard Worker // An interface that represents a single Federated Compute protocol session. 82*14675a02SAndroid Build Coastguard Worker // 83*14675a02SAndroid Build Coastguard Worker // An instance of this class represents a single session of client-server 84*14675a02SAndroid Build Coastguard Worker // interaction. Instances are generally stateful, and therefore cannot be 85*14675a02SAndroid Build Coastguard Worker // reused (each session should use a dedicated instance). 86*14675a02SAndroid Build Coastguard Worker // 87*14675a02SAndroid Build Coastguard Worker // The protocol consists of 3 phases, which must occur in the following order: 88*14675a02SAndroid Build Coastguard Worker // 1. A call to `EligibilityEvalCheckin()`. 89*14675a02SAndroid Build Coastguard Worker // 2. A call to `Checkin(...)`, only if the client wasn't rejected by the server 90*14675a02SAndroid Build Coastguard Worker // in the previous phase. 91*14675a02SAndroid Build Coastguard Worker // 3. A call to `ReportCompleted(...)` or `ReportNotCompleted(...)`, only if the 92*14675a02SAndroid Build Coastguard Worker // client wasn't rejected in the previous phase. 93*14675a02SAndroid Build Coastguard Worker class FederatedProtocol { 94*14675a02SAndroid Build Coastguard Worker public: 95*14675a02SAndroid Build Coastguard Worker virtual ~FederatedProtocol() = default; 96*14675a02SAndroid Build Coastguard Worker 97*14675a02SAndroid Build Coastguard Worker // The unparsed plan and checkpoint payload which make up a computation. The 98*14675a02SAndroid Build Coastguard Worker // data can be provided as either an std::string or an absl::Cord. 99*14675a02SAndroid Build Coastguard Worker struct PlanAndCheckpointPayloads { 100*14675a02SAndroid Build Coastguard Worker std::variant<std::string, absl::Cord> plan; 101*14675a02SAndroid Build Coastguard Worker std::variant<std::string, absl::Cord> checkpoint; 102*14675a02SAndroid Build Coastguard Worker }; 103*14675a02SAndroid Build Coastguard Worker 104*14675a02SAndroid Build Coastguard Worker // An eligibility task, consisting of task payloads and an execution ID. 105*14675a02SAndroid Build Coastguard Worker struct EligibilityEvalTask { 106*14675a02SAndroid Build Coastguard Worker PlanAndCheckpointPayloads payloads; 107*14675a02SAndroid Build Coastguard Worker std::string execution_id; 108*14675a02SAndroid Build Coastguard Worker std::optional< 109*14675a02SAndroid Build Coastguard Worker google::internal::federatedcompute::v1::PopulationEligibilitySpec> 110*14675a02SAndroid Build Coastguard Worker population_eligibility_spec; 111*14675a02SAndroid Build Coastguard Worker }; 112*14675a02SAndroid Build Coastguard Worker // A rejection of a client by the server. 113*14675a02SAndroid Build Coastguard Worker struct Rejection {}; 114*14675a02SAndroid Build Coastguard Worker // Indicates that the server does not have an eligibility eval task configured 115*14675a02SAndroid Build Coastguard Worker // for the population. 116*14675a02SAndroid Build Coastguard Worker struct EligibilityEvalDisabled {}; 117*14675a02SAndroid Build Coastguard Worker // EligibilityEvalCheckin() returns either 118*14675a02SAndroid Build Coastguard Worker // 1. an `EligibilityEvalTask` struct holding the payloads for an eligibility 119*14675a02SAndroid Build Coastguard Worker // eval task, if the population is configured with such a task. In this 120*14675a02SAndroid Build Coastguard Worker // case the caller should execute the task and pass the resulting 121*14675a02SAndroid Build Coastguard Worker // `TaskEligibilityInfo` value to the `Checkin(...)` method. 122*14675a02SAndroid Build Coastguard Worker // 2. an `EligibilityEvalDisabled` struct if the population doesn't have an 123*14675a02SAndroid Build Coastguard Worker // eligibility eval task configured. In this case the caller should 124*14675a02SAndroid Build Coastguard Worker // continue the protocol by calling the `Checkin(...)` method without 125*14675a02SAndroid Build Coastguard Worker // providing a `TaskEligibilityInfo` value. 126*14675a02SAndroid Build Coastguard Worker // 3. a `Rejection` if the server rejected this device. In this case the 127*14675a02SAndroid Build Coastguard Worker // caller 128*14675a02SAndroid Build Coastguard Worker // should end its protocol interaction. 129*14675a02SAndroid Build Coastguard Worker using EligibilityEvalCheckinResult = 130*14675a02SAndroid Build Coastguard Worker std::variant<EligibilityEvalTask, EligibilityEvalDisabled, Rejection>; 131*14675a02SAndroid Build Coastguard Worker 132*14675a02SAndroid Build Coastguard Worker // Checks in with a federated server to receive the population's eligibility 133*14675a02SAndroid Build Coastguard Worker // eval task. This method is optional and may be called 0 or 1 times. If it is 134*14675a02SAndroid Build Coastguard Worker // called, then it must be called before any call to `Checkin(...)`. 135*14675a02SAndroid Build Coastguard Worker // 136*14675a02SAndroid Build Coastguard Worker // If an eligibility eval task is configured, then the 137*14675a02SAndroid Build Coastguard Worker // `payload_uris_received_callback` function will be called with a partially 138*14675a02SAndroid Build Coastguard Worker // populated `EligibilityEvalTask` containing all of the task's info except 139*14675a02SAndroid Build Coastguard Worker // for the actual payloads (which are yet to be fetched at that point). 140*14675a02SAndroid Build Coastguard Worker // 141*14675a02SAndroid Build Coastguard Worker // Returns: 142*14675a02SAndroid Build Coastguard Worker // - On success, an EligibilityEvalCheckinResult. 143*14675a02SAndroid Build Coastguard Worker // - On error: 144*14675a02SAndroid Build Coastguard Worker // - ABORTED when one of the I/O operations got aborted by the server. 145*14675a02SAndroid Build Coastguard Worker // - CANCELLED when one of the I/O operations was interrupted by the client 146*14675a02SAndroid Build Coastguard Worker // (possibly due to a positive result from the should_abort callback). 147*14675a02SAndroid Build Coastguard Worker // - UNAVAILABLE when server cannot be reached or URI is invalid. 148*14675a02SAndroid Build Coastguard Worker // - NOT_FOUND if the server responds with NOT_FOUND, e.g. because the 149*14675a02SAndroid Build Coastguard Worker // specified population name is incorrect. 150*14675a02SAndroid Build Coastguard Worker // - UNIMPLEMENTED if an unexpected server response is received. 151*14675a02SAndroid Build Coastguard Worker // - INTERNAL if the server-provided ClientOnlyPlan cannot be parsed. (See 152*14675a02SAndroid Build Coastguard Worker // note in federated_protocol.cc for the reasoning for this.) 153*14675a02SAndroid Build Coastguard Worker // - INTERNAL for other unexpected client-side errors. 154*14675a02SAndroid Build Coastguard Worker // - any server-provided error code. 155*14675a02SAndroid Build Coastguard Worker virtual absl::StatusOr<EligibilityEvalCheckinResult> EligibilityEvalCheckin( 156*14675a02SAndroid Build Coastguard Worker std::function<void(const EligibilityEvalTask&)> 157*14675a02SAndroid Build Coastguard Worker payload_uris_received_callback) = 0; 158*14675a02SAndroid Build Coastguard Worker 159*14675a02SAndroid Build Coastguard Worker // Report an eligibility eval task error to the federated server. 160*14675a02SAndroid Build Coastguard Worker // Must only be called once and after a successful call to 161*14675a02SAndroid Build Coastguard Worker // EligibilityEvalCheckin() which returns an eligibility eval task. This 162*14675a02SAndroid Build Coastguard Worker // method is only used to report an error happened during the computation of 163*14675a02SAndroid Build Coastguard Worker // the eligibility eval task. If the eligibility eval computation succeeds, 164*14675a02SAndroid Build Coastguard Worker // the success will be reported during task assignment. 165*14675a02SAndroid Build Coastguard Worker // @param status the outcome of the eligibility eval computation. 166*14675a02SAndroid Build Coastguard Worker virtual void ReportEligibilityEvalError(absl::Status error_status) = 0; 167*14675a02SAndroid Build Coastguard Worker 168*14675a02SAndroid Build Coastguard Worker // SecAgg metadata, e.g. see SecureAggregationProtocolExecutionInfo in 169*14675a02SAndroid Build Coastguard Worker // federated_api.proto. 170*14675a02SAndroid Build Coastguard Worker struct SecAggInfo { 171*14675a02SAndroid Build Coastguard Worker int32_t expected_number_of_clients; 172*14675a02SAndroid Build Coastguard Worker int32_t minimum_clients_in_server_visible_aggregate; 173*14675a02SAndroid Build Coastguard Worker }; 174*14675a02SAndroid Build Coastguard Worker 175*14675a02SAndroid Build Coastguard Worker // A task assignment, consisting of task payloads, a URI template to download 176*14675a02SAndroid Build Coastguard Worker // federated select task slices with (if the plan uses federated select), a 177*14675a02SAndroid Build Coastguard Worker // session identifier, and SecAgg-related metadata. 178*14675a02SAndroid Build Coastguard Worker struct TaskAssignment { 179*14675a02SAndroid Build Coastguard Worker PlanAndCheckpointPayloads payloads; 180*14675a02SAndroid Build Coastguard Worker std::string federated_select_uri_template; 181*14675a02SAndroid Build Coastguard Worker std::string aggregation_session_id; 182*14675a02SAndroid Build Coastguard Worker std::optional<SecAggInfo> sec_agg_info; 183*14675a02SAndroid Build Coastguard Worker }; 184*14675a02SAndroid Build Coastguard Worker // Checkin() returns either 185*14675a02SAndroid Build Coastguard Worker // 1. a `TaskAssignment` struct if the client was assigned a task to run, or 186*14675a02SAndroid Build Coastguard Worker // 2. a `Rejection` struct if the server rejected this device. 187*14675a02SAndroid Build Coastguard Worker using CheckinResult = std::variant<TaskAssignment, Rejection>; 188*14675a02SAndroid Build Coastguard Worker 189*14675a02SAndroid Build Coastguard Worker // Checks in with a federated server. Must only be called once. If the 190*14675a02SAndroid Build Coastguard Worker // `EligibilityEvalCheckin()` method was previously called, then this method 191*14675a02SAndroid Build Coastguard Worker // must only be called if the result of that call was not a `Rejection`. 192*14675a02SAndroid Build Coastguard Worker // 193*14675a02SAndroid Build Coastguard Worker // If the caller previously called `EligibilityEvalCheckin()` and: 194*14675a02SAndroid Build Coastguard Worker // - received a payload, then the `TaskEligibilityInfo` value computed by that 195*14675a02SAndroid Build Coastguard Worker // payload must be provided via the `task_eligibility_info` parameter. 196*14675a02SAndroid Build Coastguard Worker // - received an `EligibilityEvalDisabled` result, then the 197*14675a02SAndroid Build Coastguard Worker // `task_eligibility_info` parameter should be left empty. 198*14675a02SAndroid Build Coastguard Worker // 199*14675a02SAndroid Build Coastguard Worker // If the caller did not previously call `EligibilityEvalCheckin()`, then the 200*14675a02SAndroid Build Coastguard Worker // `task_eligibility_info` parameter should be left empty. 201*14675a02SAndroid Build Coastguard Worker // 202*14675a02SAndroid Build Coastguard Worker // If the client is assigned a task by the server, then the 203*14675a02SAndroid Build Coastguard Worker // `payload_uris_received_callback` function will be called with a partially 204*14675a02SAndroid Build Coastguard Worker // populated `TaskAssignment` containing all of the task's info except for the 205*14675a02SAndroid Build Coastguard Worker // actual payloads (which are yet to be fetched at that point) 206*14675a02SAndroid Build Coastguard Worker // 207*14675a02SAndroid Build Coastguard Worker // Returns: 208*14675a02SAndroid Build Coastguard Worker // - On success, a `CheckinResult`. 209*14675a02SAndroid Build Coastguard Worker // - On error: 210*14675a02SAndroid Build Coastguard Worker // - ABORTED when one of the I/O operations got aborted by the server. 211*14675a02SAndroid Build Coastguard Worker // - CANCELLED when one of the I/O operations was interrupted by the client 212*14675a02SAndroid Build Coastguard Worker // (possibly due to a positive result from the should_abort callback). 213*14675a02SAndroid Build Coastguard Worker // - UNAVAILABLE when server cannot be reached or URI is invalid. 214*14675a02SAndroid Build Coastguard Worker // - NOT_FOUND if the server responds with NOT_FOUND, e.g. because the 215*14675a02SAndroid Build Coastguard Worker // specified population name is incorrect. 216*14675a02SAndroid Build Coastguard Worker // - UNIMPLEMENTED if an unexpected server response is received. 217*14675a02SAndroid Build Coastguard Worker // - INTERNAL if the server-provided ClientOnlyPlan cannot be parsed. (See 218*14675a02SAndroid Build Coastguard Worker // note in federated_protocol.cc for the reasoning for this.) 219*14675a02SAndroid Build Coastguard Worker // - INTERNAL for other unexpected client-side errors. 220*14675a02SAndroid Build Coastguard Worker // - any server-provided error code. 221*14675a02SAndroid Build Coastguard Worker // TODO(team): Replace this reference to protocol-specific 222*14675a02SAndroid Build Coastguard Worker // TaskEligibilityInfo proto with a protocol-agnostic struct. 223*14675a02SAndroid Build Coastguard Worker virtual absl::StatusOr<CheckinResult> Checkin( 224*14675a02SAndroid Build Coastguard Worker const std::optional< 225*14675a02SAndroid Build Coastguard Worker google::internal::federatedml::v2::TaskEligibilityInfo>& 226*14675a02SAndroid Build Coastguard Worker task_eligibility_info, 227*14675a02SAndroid Build Coastguard Worker std::function<void(const TaskAssignment&)> 228*14675a02SAndroid Build Coastguard Worker payload_uris_received_callback) = 0; 229*14675a02SAndroid Build Coastguard Worker 230*14675a02SAndroid Build Coastguard Worker // A list of absl::StatusOr<TaskAssignment> returned by 231*14675a02SAndroid Build Coastguard Worker // PerformMultipleTaskAssignments. Individual absl::StatusOr<TaskAssignment> 232*14675a02SAndroid Build Coastguard Worker // may be an error status due to failed to fetch the plan resources. 233*14675a02SAndroid Build Coastguard Worker struct MultipleTaskAssignments { 234*14675a02SAndroid Build Coastguard Worker std::vector<absl::StatusOr<TaskAssignment>> task_assignments; 235*14675a02SAndroid Build Coastguard Worker }; 236*14675a02SAndroid Build Coastguard Worker 237*14675a02SAndroid Build Coastguard Worker // Checks in with a federated server to get multiple task assignments. 238*14675a02SAndroid Build Coastguard Worker // 239*14675a02SAndroid Build Coastguard Worker // Must only be called once after the following conditions are met: 240*14675a02SAndroid Build Coastguard Worker // 241*14675a02SAndroid Build Coastguard Worker // - the caller previously called `EligibilityEvalCheckin()` and, 242*14675a02SAndroid Build Coastguard Worker // - received a payload, and the returned EligibilityEvalTask's 243*14675a02SAndroid Build Coastguard Worker // `PopulationEligibilitySpec` contained at least one task with 244*14675a02SAndroid Build Coastguard Worker // TASK_ASSIGNMENT_MODE_MULTIPLE, for which the device is eligible. 245*14675a02SAndroid Build Coastguard Worker // 246*14675a02SAndroid Build Coastguard Worker // 247*14675a02SAndroid Build Coastguard Worker // Returns: 248*14675a02SAndroid Build Coastguard Worker // - On success, a `MultipleTaskAssignments`. 249*14675a02SAndroid Build Coastguard Worker // - On error: 250*14675a02SAndroid Build Coastguard Worker // - ABORTED when one of the I/O operations got aborted by the server. 251*14675a02SAndroid Build Coastguard Worker // - CANCELLED when one of the I/O operations was interrupted by the client 252*14675a02SAndroid Build Coastguard Worker // (possibly due to a positive result from the should_abort callback). 253*14675a02SAndroid Build Coastguard Worker // - UNAVAILABLE when server cannot be reached or URI is invalid. 254*14675a02SAndroid Build Coastguard Worker // - NOT_FOUND if the server responds with NOT_FOUND, e.g. because the 255*14675a02SAndroid Build Coastguard Worker // specified population name is incorrect. 256*14675a02SAndroid Build Coastguard Worker // - UNIMPLEMENTED if an unexpected server response is received. 257*14675a02SAndroid Build Coastguard Worker // - INTERNAL for other unexpected client-side errors. 258*14675a02SAndroid Build Coastguard Worker // - any server-provided error code. 259*14675a02SAndroid Build Coastguard Worker virtual absl::StatusOr<MultipleTaskAssignments> 260*14675a02SAndroid Build Coastguard Worker PerformMultipleTaskAssignments( 261*14675a02SAndroid Build Coastguard Worker const std::vector<std::string>& task_names) = 0; 262*14675a02SAndroid Build Coastguard Worker 263*14675a02SAndroid Build Coastguard Worker // Reports the result of a federated computation to the server. Must only be 264*14675a02SAndroid Build Coastguard Worker // called once and after a successful call to Checkin(). 265*14675a02SAndroid Build Coastguard Worker // @param checkpoint A checkpoint proto. 266*14675a02SAndroid Build Coastguard Worker // @param stats all stats reported during the computation. 267*14675a02SAndroid Build Coastguard Worker // @param plan_duration the duration for executing the plan in the plan 268*14675a02SAndroid Build Coastguard Worker // engine. Does not include time spent on downloading the plan. 269*14675a02SAndroid Build Coastguard Worker // Returns: 270*14675a02SAndroid Build Coastguard Worker // - On success, OK. 271*14675a02SAndroid Build Coastguard Worker // - On error (e.g. an interruption, network error, or other unexpected 272*14675a02SAndroid Build Coastguard Worker // error): 273*14675a02SAndroid Build Coastguard Worker // - ABORTED when one of the I/O operations got aborted by the server. 274*14675a02SAndroid Build Coastguard Worker // - CANCELLED when one of the I/O operations was interrupted by the client 275*14675a02SAndroid Build Coastguard Worker // (possibly due to a positive result from the should_abort callback). 276*14675a02SAndroid Build Coastguard Worker // - UNIMPLEMENTED if the server responded with an unexpected response 277*14675a02SAndroid Build Coastguard Worker // message. 278*14675a02SAndroid Build Coastguard Worker // - INTERNAL for other unexpected client-side errors. 279*14675a02SAndroid Build Coastguard Worker // - any server-provided error code. 280*14675a02SAndroid Build Coastguard Worker virtual absl::Status ReportCompleted( 281*14675a02SAndroid Build Coastguard Worker ComputationResults results, absl::Duration plan_duration, 282*14675a02SAndroid Build Coastguard Worker std::optional<std::string> aggregation_session_id) = 0; 283*14675a02SAndroid Build Coastguard Worker 284*14675a02SAndroid Build Coastguard Worker // Reports the unsuccessful result of a federated computation to the server. 285*14675a02SAndroid Build Coastguard Worker // Must only be called once and after a successful call to Checkin(). 286*14675a02SAndroid Build Coastguard Worker // @param phase_outcome the outcome of the federated computation. 287*14675a02SAndroid Build Coastguard Worker // @param plan_duration the duration for executing the plan in the plan 288*14675a02SAndroid Build Coastguard Worker // engine. Does not include time spent on downloading the plan. 289*14675a02SAndroid Build Coastguard Worker // Returns: 290*14675a02SAndroid Build Coastguard Worker // - On success, OK. 291*14675a02SAndroid Build Coastguard Worker // - On error: 292*14675a02SAndroid Build Coastguard Worker // - ABORTED when one of the I/O operations got aborted by the server. 293*14675a02SAndroid Build Coastguard Worker // - CANCELLED when one of the I/O operations was interrupted by the client 294*14675a02SAndroid Build Coastguard Worker // (possibly due to a positive result from the should_abort callback). 295*14675a02SAndroid Build Coastguard Worker // - UNIMPLEMENTED if the server responded with an unexpected response 296*14675a02SAndroid Build Coastguard Worker // message, or if the results to report require SecAgg support. 297*14675a02SAndroid Build Coastguard Worker // - INTERNAL for other unexpected client-side errors. 298*14675a02SAndroid Build Coastguard Worker // - any server-provided error code. 299*14675a02SAndroid Build Coastguard Worker virtual absl::Status ReportNotCompleted( 300*14675a02SAndroid Build Coastguard Worker engine::PhaseOutcome phase_outcome, absl::Duration plan_duration, 301*14675a02SAndroid Build Coastguard Worker std::optional<std::string> aggregation_session_id) = 0; 302*14675a02SAndroid Build Coastguard Worker 303*14675a02SAndroid Build Coastguard Worker // Returns the RetryWindow the caller should use when rescheduling, based on 304*14675a02SAndroid Build Coastguard Worker // the current protocol phase. The value returned by this method may change 305*14675a02SAndroid Build Coastguard Worker // after every interaction with the protocol, so callers should call this 306*14675a02SAndroid Build Coastguard Worker // right before ending their interactions with the FederatedProtocol object to 307*14675a02SAndroid Build Coastguard Worker // ensure they use the most recent value. 308*14675a02SAndroid Build Coastguard Worker // TODO(team): Replace this reference to protocol-specific 309*14675a02SAndroid Build Coastguard Worker // RetryWindow proto with a protocol-agnostic struct (or just a single 310*14675a02SAndroid Build Coastguard Worker // absl::Duration). 311*14675a02SAndroid Build Coastguard Worker virtual google::internal::federatedml::v2::RetryWindow 312*14675a02SAndroid Build Coastguard Worker GetLatestRetryWindow() = 0; 313*14675a02SAndroid Build Coastguard Worker 314*14675a02SAndroid Build Coastguard Worker // Returns the best estimate of the total bytes downloaded and uploaded over 315*14675a02SAndroid Build Coastguard Worker // the network, plus the best estimate of the duration of wall clock time 316*14675a02SAndroid Build Coastguard Worker // spent waiting for network requests to finish (but, for example, excluding 317*14675a02SAndroid Build Coastguard Worker // any idle time spent waiting between issuing polling requests). 318*14675a02SAndroid Build Coastguard Worker // 319*14675a02SAndroid Build Coastguard Worker // Note that this estimate may still include time spent simply waiting for a 320*14675a02SAndroid Build Coastguard Worker // server response, even if no data was being sent or received during that 321*14675a02SAndroid Build Coastguard Worker // time. E.g. in the case of the legacy gRPC protocol where the single checkin 322*14675a02SAndroid Build Coastguard Worker // request blocks until a task is assigned to the client. 323*14675a02SAndroid Build Coastguard Worker // 324*14675a02SAndroid Build Coastguard Worker // If possible, this estimate should also include time spent 325*14675a02SAndroid Build Coastguard Worker // compressing/decompressing payloads before writing them to or after reading 326*14675a02SAndroid Build Coastguard Worker // them from the network. 327*14675a02SAndroid Build Coastguard Worker virtual NetworkStats GetNetworkStats() = 0; 328*14675a02SAndroid Build Coastguard Worker 329*14675a02SAndroid Build Coastguard Worker protected: 330*14675a02SAndroid Build Coastguard Worker // A list of states representing the sequence of calls we expect to receive 331*14675a02SAndroid Build Coastguard Worker // via this interface, as well as their possible outcomes. Implementations of 332*14675a02SAndroid Build Coastguard Worker // this class are likely to share these coarse-grained states, and use them to 333*14675a02SAndroid Build Coastguard Worker // determine which values to return from `GetLatestRetryWindow()`. 334*14675a02SAndroid Build Coastguard Worker enum class ObjectState { 335*14675a02SAndroid Build Coastguard Worker // The initial object state. 336*14675a02SAndroid Build Coastguard Worker kInitialized, 337*14675a02SAndroid Build Coastguard Worker // EligibilityEvalCheckin() was called but it failed with a 'transient' 338*14675a02SAndroid Build Coastguard Worker // error (e.g. an UNAVAILABLE network error, although the set of transient 339*14675a02SAndroid Build Coastguard Worker // errors is flag-defined). 340*14675a02SAndroid Build Coastguard Worker kEligibilityEvalCheckinFailed, 341*14675a02SAndroid Build Coastguard Worker // EligibilityEvalCheckin() was called but it failed with a 'permanent' 342*14675a02SAndroid Build Coastguard Worker // error (e.g. a NOT_FOUND network error, although the set of permanent 343*14675a02SAndroid Build Coastguard Worker // errors is flag-defined). 344*14675a02SAndroid Build Coastguard Worker kEligibilityEvalCheckinFailedPermanentError, 345*14675a02SAndroid Build Coastguard Worker // EligibilityEvalCheckin() was called, and the server rejected the client. 346*14675a02SAndroid Build Coastguard Worker kEligibilityEvalCheckinRejected, 347*14675a02SAndroid Build Coastguard Worker // EligibilityEvalCheckin() was called, and the server did not return an 348*14675a02SAndroid Build Coastguard Worker // eligibility eval payload. 349*14675a02SAndroid Build Coastguard Worker kEligibilityEvalDisabled, 350*14675a02SAndroid Build Coastguard Worker // EligibilityEvalCheckin() was called, and the server did return an 351*14675a02SAndroid Build Coastguard Worker // eligibility eval payload, which must then be run to produce a 352*14675a02SAndroid Build Coastguard Worker // TaskEligibilityInfo value. 353*14675a02SAndroid Build Coastguard Worker kEligibilityEvalEnabled, 354*14675a02SAndroid Build Coastguard Worker // Checkin(...) was called but it failed with a 'transient' error. 355*14675a02SAndroid Build Coastguard Worker kCheckinFailed, 356*14675a02SAndroid Build Coastguard Worker // Checkin(...) was called but it failed with a 'permanent' error. 357*14675a02SAndroid Build Coastguard Worker kCheckinFailedPermanentError, 358*14675a02SAndroid Build Coastguard Worker // Checkin(...) was called, and the server rejected the client. 359*14675a02SAndroid Build Coastguard Worker kCheckinRejected, 360*14675a02SAndroid Build Coastguard Worker // Checkin(...) was called, and the server accepted the client and returned 361*14675a02SAndroid Build Coastguard Worker // a payload, which must then be run to produce a report. 362*14675a02SAndroid Build Coastguard Worker kCheckinAccepted, 363*14675a02SAndroid Build Coastguard Worker // PerformMultipleTaskAssignments(...) was called but it failed with a 364*14675a02SAndroid Build Coastguard Worker // 'transient' error, without receiving a single task assignment. If some 365*14675a02SAndroid Build Coastguard Worker // task assignments were successfully received, but some others failed (e.g. 366*14675a02SAndroid Build Coastguard Worker // because their resources failed to be downloaded), then this state won't 367*14675a02SAndroid Build Coastguard Worker // be used. 368*14675a02SAndroid Build Coastguard Worker kMultipleTaskAssignmentsFailed, 369*14675a02SAndroid Build Coastguard Worker // PerformMultipleTaskAssignments(...) was called but it failed with a 370*14675a02SAndroid Build Coastguard Worker // 'permanent' error. 371*14675a02SAndroid Build Coastguard Worker kMultipleTaskAssignmentsFailedPermanentError, 372*14675a02SAndroid Build Coastguard Worker // PerformMultipleTaskAssignments(...) was called but an empty list of tasks 373*14675a02SAndroid Build Coastguard Worker // is returned by the server. 374*14675a02SAndroid Build Coastguard Worker kMultipleTaskAssignmentsNoAvailableTask, 375*14675a02SAndroid Build Coastguard Worker // PerformMultipleTaskAssignments(...) was called, and the server accepted 376*14675a02SAndroid Build Coastguard Worker // the client and returned one or more payload, which must then be run to 377*14675a02SAndroid Build Coastguard Worker // produce a report. 378*14675a02SAndroid Build Coastguard Worker kMultipleTaskAssignmentsAccepted, 379*14675a02SAndroid Build Coastguard Worker // Report(...) was called. 380*14675a02SAndroid Build Coastguard Worker kReportCalled, 381*14675a02SAndroid Build Coastguard Worker // Report(...) was called and it resulted in a 'permanent' error. 382*14675a02SAndroid Build Coastguard Worker // 383*14675a02SAndroid Build Coastguard Worker // Note: there is no kReportFailed (corresponding to 'transient' errors, 384*14675a02SAndroid Build Coastguard Worker // like the other phases have), because by the time the report phase is 385*14675a02SAndroid Build Coastguard Worker // reached, a set of RetryWindows is guaranteed to have been received from 386*14675a02SAndroid Build Coastguard Worker // the server. 387*14675a02SAndroid Build Coastguard Worker kReportFailedPermanentError, 388*14675a02SAndroid Build Coastguard Worker // Report(...) was called for multiple tasks, and only a subset of the tasks 389*14675a02SAndroid Build Coastguard Worker // succeed. 390*14675a02SAndroid Build Coastguard Worker kReportMultipleTaskPartialError, 391*14675a02SAndroid Build Coastguard Worker }; 392*14675a02SAndroid Build Coastguard Worker }; 393*14675a02SAndroid Build Coastguard Worker 394*14675a02SAndroid Build Coastguard Worker } // namespace client 395*14675a02SAndroid Build Coastguard Worker } // namespace fcp 396*14675a02SAndroid Build Coastguard Worker 397*14675a02SAndroid Build Coastguard Worker #endif // FCP_CLIENT_FEDERATED_PROTOCOL_H_ 398