1 /**
2 * Copyright 2021 Huawei Technologies Co., Ltd
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "fl/armour/cipher/cipher_shares.h"
18 #include "fl/server/common.h"
19 #include "fl/armour/cipher/cipher_meta_storage.h"
20
21 namespace mindspore {
22 namespace armour {
ShareSecrets(const int cur_iterator,const schema::RequestShareSecrets * share_secrets_req,const std::shared_ptr<fl::server::FBBuilder> & share_secrets_resp_builder,const string next_req_time)23 bool CipherShares::ShareSecrets(const int cur_iterator, const schema::RequestShareSecrets *share_secrets_req,
24 const std::shared_ptr<fl::server::FBBuilder> &share_secrets_resp_builder,
25 const string next_req_time) {
26 MS_LOG(INFO) << "CipherShares::ShareSecrets START";
27 if (share_secrets_req == nullptr) {
28 std::string reason = "Request is nullptr";
29 MS_LOG(ERROR) << reason;
30 BuildShareSecretsRsp(share_secrets_resp_builder, schema::ResponseCode_RequestError, reason, next_req_time,
31 cur_iterator);
32 return false;
33 }
34 if (cipher_init_ == nullptr) {
35 std::string reason = "cipher_init_ is nullptr";
36 MS_LOG(ERROR) << reason;
37 BuildShareSecretsRsp(share_secrets_resp_builder, schema::ResponseCode_SystemError, reason, next_req_time,
38 cur_iterator);
39 return false;
40 }
41 // step 1: get client list and share secrets from memory server.
42 clock_t start_time = clock();
43
44 int iteration = share_secrets_req->iteration();
45 std::vector<std::string> get_keys_clients;
46 cipher_init_->cipher_meta_storage_.GetClientListFromServer(fl::server::kCtxGetKeysClientList, &get_keys_clients);
47 std::vector<std::string> clients_share_list;
48 cipher_init_->cipher_meta_storage_.GetClientListFromServer(fl::server::kCtxShareSecretsClientList,
49 &clients_share_list);
50
51 std::map<std::string, std::vector<clientshare_str>> encrypted_shares_all;
52 cipher_init_->cipher_meta_storage_.GetClientSharesFromServer(fl::server::kCtxClientsEncryptedShares,
53 &encrypted_shares_all);
54
55 MS_LOG(INFO) << "Client of get keys size : " << get_keys_clients.size()
56 << "client of update shares size : " << clients_share_list.size()
57 << "updated shares size: " << encrypted_shares_all.size();
58
59 // step 2: update new item to memory server. serialise: update pb struct to memory server.
60
61 std::string fl_id_src = share_secrets_req->fl_id()->str();
62 if (find(get_keys_clients.begin(), get_keys_clients.end(), fl_id_src) == get_keys_clients.end()) {
63 // the client not in get keys clients
64 BuildShareSecretsRsp(share_secrets_resp_builder, schema::ResponseCode_RequestError,
65 ("client share secret is not in getkeys list. && client is illegal"), next_req_time,
66 iteration);
67 return false;
68 }
69
70 if (encrypted_shares_all.find(fl_id_src) != encrypted_shares_all.end()) { // the client is already exists
71 BuildShareSecretsRsp(share_secrets_resp_builder, schema::ResponseCode_SUCCEED,
72 ("client sharesecret already exists."), next_req_time, iteration);
73 return false;
74 }
75
76 // update new item to memory server.
77 const flatbuffers::Vector<flatbuffers::Offset<mindspore::schema::ClientShare>> *encrypted_shares =
78 (share_secrets_req->encrypted_shares());
79 bool retcode_client =
80 cipher_init_->cipher_meta_storage_.UpdateClientToServer(fl::server::kCtxShareSecretsClientList, fl_id_src);
81 bool retcode_share = cipher_init_->cipher_meta_storage_.UpdateClientShareToServer(
82 fl::server::kCtxClientsEncryptedShares, fl_id_src, encrypted_shares);
83 if (!(retcode_share && retcode_client)) {
84 BuildShareSecretsRsp(share_secrets_resp_builder, schema::ResponseCode_OutOfTime,
85 "update client of shares and shares failed", next_req_time, iteration);
86 MS_LOG(ERROR) << "CipherShares::ShareSecrets update client of shares and shares failed ";
87 return false;
88 }
89 BuildShareSecretsRsp(share_secrets_resp_builder, schema::ResponseCode_SUCCEED, "OK", next_req_time, iteration);
90 MS_LOG(INFO) << "CipherShares::ShareSecrets Success";
91 clock_t end_time = clock();
92 double duration = static_cast<double>((end_time - start_time) * 1.0 / CLOCKS_PER_SEC);
93 MS_LOG(INFO) << "ShareSecrets get + deal + update data time is : " << duration;
94 return true;
95 }
96
GetSecrets(const schema::GetShareSecrets * get_secrets_req,const std::shared_ptr<fl::server::FBBuilder> & fbb,const std::string & next_req_time)97 bool CipherShares::GetSecrets(const schema::GetShareSecrets *get_secrets_req,
98 const std::shared_ptr<fl::server::FBBuilder> &fbb, const std::string &next_req_time) {
99 MS_LOG(INFO) << "CipherShares::GetSecrets START";
100 clock_t start_time = clock();
101 // step 0: check whether the parameters are legal.
102 if (get_secrets_req == nullptr) {
103 BuildGetSecretsRsp(fbb, schema::ResponseCode_RequestError, 0, next_req_time, nullptr);
104 MS_LOG(ERROR) << "GetSecrets: get_secrets_req is nullptr.";
105 return false;
106 }
107 int iteration = get_secrets_req->iteration();
108 if (cipher_init_ == nullptr) {
109 MS_LOG(ERROR) << "cipher_init_ is nullptr";
110 BuildGetSecretsRsp(fbb, schema::ResponseCode_SystemError, IntToSize(iteration), next_req_time, nullptr);
111 return false;
112 }
113 // step 1: get client list and client shares list from memory server.
114 std::map<std::string, std::vector<clientshare_str>> encrypted_shares_all;
115 cipher_init_->cipher_meta_storage_.GetClientSharesFromServer(fl::server::kCtxClientsEncryptedShares,
116 &encrypted_shares_all);
117 size_t encrypted_shares_num = encrypted_shares_all.size();
118 if (cipher_init_->share_secrets_threshold > encrypted_shares_num) { // the client num is not enough, return false.
119 BuildGetSecretsRsp(fbb, schema::ResponseCode_SucNotReady, IntToSize(iteration), next_req_time, nullptr);
120 MS_LOG(INFO) << "GetSecrets: the encrypted shares num is not enough: share_secrets_threshold: "
121 << cipher_init_->share_secrets_threshold << "encrypted_shares_num: " << encrypted_shares_num;
122 return false;
123 }
124
125 std::string fl_id = get_secrets_req->fl_id()->str();
126 // the client is not in share secrets client list.
127 if (encrypted_shares_all.find(fl_id) == encrypted_shares_all.end()) {
128 BuildGetSecretsRsp(fbb, schema::ResponseCode_RequestError, IntToSize(iteration), next_req_time, nullptr);
129 MS_LOG(ERROR) << "GetSecrets: client is not in share secrets client list.";
130 return false;
131 }
132
133 bool retcode_client =
134 cipher_init_->cipher_meta_storage_.UpdateClientToServer(fl::server::kCtxGetSecretsClientList, fl_id);
135 if (!retcode_client) {
136 MS_LOG(ERROR) << "update get secrets clients failed";
137 BuildGetSecretsRsp(fbb, schema::ResponseCode_SucNotReady, IntToSize(iteration), next_req_time, nullptr);
138 return false;
139 }
140
141 // get the result client shares.
142 std::vector<clientshare_str> encrypted_shares_add;
143 for (auto encrypted_shares_iterator = encrypted_shares_all.begin();
144 encrypted_shares_iterator != encrypted_shares_all.end(); ++encrypted_shares_iterator) {
145 std::string fl_id_src_now = encrypted_shares_iterator->first;
146 std::vector<clientshare_str> &clientshare_str_now = encrypted_shares_iterator->second;
147 clientshare_str client_share_str_new;
148 bool find_flag = false;
149 for (size_t index_clientshare = 0; index_clientshare < clientshare_str_now.size(); ++index_clientshare) {
150 std::string fl_id_des = clientshare_str_now[index_clientshare].fl_id;
151 if (fl_id_des == fl_id) {
152 client_share_str_new.fl_id = fl_id_src_now;
153 client_share_str_new.index = clientshare_str_now[index_clientshare].index;
154 client_share_str_new.share = clientshare_str_now[index_clientshare].share;
155 find_flag = true;
156 break;
157 }
158 }
159 if (find_flag) {
160 encrypted_shares_add.push_back(client_share_str_new);
161 }
162 }
163
164 // serialise clientshares
165 size_t size_shares = encrypted_shares_add.size();
166 std::vector<flatbuffers::Offset<mindspore::schema::ClientShare>> encrypted_shares;
167 std::vector<clientshare_str>::iterator ptr_start = encrypted_shares_add.begin();
168 std::vector<clientshare_str>::iterator ptr_end = ptr_start + size_shares;
169 for (std::vector<clientshare_str>::iterator ptr = ptr_start; ptr < ptr_end; ++ptr) {
170 auto one_fl_id = fbb->CreateString(ptr->fl_id);
171 auto two_share = fbb->CreateVector(ptr->share.data(), ptr->share.size());
172 auto third_index = ptr->index;
173 auto one_clientshare = schema::CreateClientShare(*fbb, one_fl_id, two_share, third_index);
174 encrypted_shares.push_back(one_clientshare);
175 }
176
177 BuildGetSecretsRsp(fbb, schema::ResponseCode_SUCCEED, IntToSize(iteration), next_req_time, &encrypted_shares);
178 MS_LOG(INFO) << "CipherShares::GetSecrets Success";
179 clock_t end_time = clock();
180 double duration = static_cast<double>((end_time - start_time) * 1.0 / CLOCKS_PER_SEC);
181 MS_LOG(INFO) << "Getsecrets Duration Time is : " << duration;
182 return true;
183 }
184
BuildGetSecretsRsp(const std::shared_ptr<fl::server::FBBuilder> & fbb,const schema::ResponseCode retcode,size_t iteration,const std::string & next_req_time,const std::vector<flatbuffers::Offset<mindspore::schema::ClientShare>> * encrypted_shares)185 void CipherShares::BuildGetSecretsRsp(
186 const std::shared_ptr<fl::server::FBBuilder> &fbb, const schema::ResponseCode retcode, size_t iteration,
187 const std::string &next_req_time,
188 const std::vector<flatbuffers::Offset<mindspore::schema::ClientShare>> *encrypted_shares) {
189 int rsp_retcode = retcode;
190 int rsp_iteration = SizeToInt(iteration);
191 auto rsp_next_req_time = fbb->CreateString(next_req_time);
192 if (encrypted_shares == nullptr) {
193 auto get_secrets_rsp = schema::CreateReturnShareSecrets(*fbb, rsp_retcode, rsp_iteration, 0, rsp_next_req_time);
194 fbb->Finish(get_secrets_rsp);
195 } else {
196 auto encrypted_shares_rsp = fbb->CreateVector(*encrypted_shares);
197 auto get_secrets_rsp =
198 CreateReturnShareSecrets(*fbb, rsp_retcode, rsp_iteration, encrypted_shares_rsp, rsp_next_req_time);
199 fbb->Finish(get_secrets_rsp);
200 }
201 return;
202 }
203
BuildShareSecretsRsp(const std::shared_ptr<fl::server::FBBuilder> & share_secrets_resp_builder,const schema::ResponseCode retcode,const string & reason,const string & next_req_time,const int iteration)204 void CipherShares::BuildShareSecretsRsp(const std::shared_ptr<fl::server::FBBuilder> &share_secrets_resp_builder,
205 const schema::ResponseCode retcode, const string &reason,
206 const string &next_req_time, const int iteration) {
207 auto rsp_reason = share_secrets_resp_builder->CreateString(reason);
208 auto rsp_next_req_time = share_secrets_resp_builder->CreateString(next_req_time);
209 auto share_secrets_rsp =
210 schema::CreateResponseShareSecrets(*share_secrets_resp_builder, retcode, rsp_reason, rsp_next_req_time, iteration);
211 share_secrets_resp_builder->Finish(share_secrets_rsp);
212 return;
213 }
214
ClearShareSecrets()215 void CipherShares::ClearShareSecrets() {
216 fl::server::DistributedMetadataStore::GetInstance().ResetMetadata(fl::server::kCtxShareSecretsClientList);
217 fl::server::DistributedMetadataStore::GetInstance().ResetMetadata(fl::server::kCtxClientsEncryptedShares);
218 fl::server::DistributedMetadataStore::GetInstance().ResetMetadata(fl::server::kCtxGetSecretsClientList);
219 }
220 } // namespace armour
221 } // namespace mindspore
222