This is an automated email from the ASF dual-hosted git repository.
mssun pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/incubator-teaclave.git
The following commit(s) were added to refs/heads/develop by this push:
new 2fa546e [services] Unify Fusion Data and InputFile/OutputFile (#230)
2fa546e is described below
commit 2fa546e524b994bdf8640f08a5e732e87b5a69b5
Author: TX <[email protected]>
AuthorDate: Thu Feb 27 11:55:22 2020 -0800
[services] Unify Fusion Data and InputFile/OutputFile (#230)
---
services/frontend/enclave/src/service.rs | 30 +-
services/management/enclave/src/file.rs | 108 -----
services/management/enclave/src/function.rs | 79 ----
services/management/enclave/src/fusion_data.rs | 70 ---
services/management/enclave/src/lib.rs | 4 +-
services/management/enclave/src/service.rs | 495 ++++++++++-----------
services/management/enclave/src/task.rs | 461 ++++++-------------
services/proto/src/proto/teaclave_common.proto | 9 +
.../src/proto/teaclave_frontend_service.proto | 52 ++-
.../src/proto/teaclave_management_service.proto | 4 +-
services/proto/src/teaclave_common.rs | 29 +-
services/proto/src/teaclave_frontend_service.rs | 359 ++++++++-------
services/proto/src/teaclave_management_service.rs | 12 +-
.../enclave/src/teaclave_frontend_service.rs | 90 +++-
.../enclave/src/teaclave_management_service.rs | 236 ++++++----
types/src/file.rs | 109 ++---
types/src/function.rs | 58 +++
types/src/lib.rs | 8 +
types/src/staged_task.rs | 84 ++++
types/src/storage.rs | 37 ++
types/src/task.rs | 48 ++
types/src/worker.rs | 6 +-
22 files changed, 1220 insertions(+), 1168 deletions(-)
diff --git a/services/frontend/enclave/src/service.rs
b/services/frontend/enclave/src/service.rs
index f4e50c3..dea5f81 100644
--- a/services/frontend/enclave/src/service.rs
+++ b/services/frontend/enclave/src/service.rs
@@ -10,11 +10,12 @@ use teaclave_proto::teaclave_common::UserCredential;
use teaclave_proto::teaclave_frontend_service::{
ApproveTaskRequest, ApproveTaskResponse, AssignDataRequest,
AssignDataResponse,
CreateTaskRequest, CreateTaskResponse, GetFunctionRequest,
GetFunctionResponse,
- GetFusionDataRequest, GetFusionDataResponse, GetOutputFileRequest,
GetOutputFileResponse,
+ GetInputFileRequest, GetInputFileResponse, GetOutputFileRequest,
GetOutputFileResponse,
GetTaskRequest, GetTaskResponse, InvokeTaskRequest, InvokeTaskResponse,
- RegisterFunctionRequest, RegisterFunctionResponse,
RegisterInputFileRequest,
- RegisterInputFileResponse, RegisterOutputFileRequest,
RegisterOutputFileResponse,
- TeaclaveFrontend,
+ RegisterFunctionRequest, RegisterFunctionResponse,
RegisterFusionOutputRequest,
+ RegisterFusionOutputResponse, RegisterInputFileRequest,
RegisterInputFileResponse,
+ RegisterInputFromOutputRequest, RegisterInputFromOutputResponse,
RegisterOutputFileRequest,
+ RegisterOutputFileResponse, TeaclaveFrontend,
};
use teaclave_proto::teaclave_management_service::TeaclaveManagementClient;
use teaclave_rpc::endpoint::Endpoint;
@@ -124,6 +125,19 @@ impl TeaclaveFrontend for TeaclaveFrontendService {
authentication_and_forward_to_management!(self, request,
register_output_file)
}
+ fn register_fusion_output(
+ &self,
+ request: Request<RegisterFusionOutputRequest>,
+ ) -> TeaclaveServiceResponseResult<RegisterFusionOutputResponse> {
+ authentication_and_forward_to_management!(self, request,
register_fusion_output)
+ }
+
+ fn register_input_from_output(
+ &self,
+ request: Request<RegisterInputFromOutputRequest>,
+ ) -> TeaclaveServiceResponseResult<RegisterInputFromOutputResponse> {
+ authentication_and_forward_to_management!(self, request,
register_input_from_output)
+ }
fn get_output_file(
&self,
request: Request<GetOutputFileRequest>,
@@ -131,11 +145,11 @@ impl TeaclaveFrontend for TeaclaveFrontendService {
authentication_and_forward_to_management!(self, request,
get_output_file)
}
- fn get_fusion_data(
+ fn get_input_file(
&self,
- request: Request<GetFusionDataRequest>,
- ) -> TeaclaveServiceResponseResult<GetFusionDataResponse> {
- authentication_and_forward_to_management!(self, request,
get_fusion_data)
+ request: Request<GetInputFileRequest>,
+ ) -> TeaclaveServiceResponseResult<GetInputFileResponse> {
+ authentication_and_forward_to_management!(self, request,
get_input_file)
}
fn register_function(
diff --git a/services/management/enclave/src/file.rs
b/services/management/enclave/src/file.rs
deleted file mode 100644
index 6e398ef..0000000
--- a/services/management/enclave/src/file.rs
+++ /dev/null
@@ -1,108 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements. See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership. The ASF licenses this file
-// to you 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.
-use anyhow::{anyhow, Result};
-use serde::{Deserialize, Serialize};
-use serde_json;
-use std::prelude::v1::*;
-use teaclave_types::TeaclaveFileCryptoInfo;
-use url::Url;
-use uuid::Uuid;
-
-const INPUT_FILE_PREFIX: &str = "input-file-";
-const OUTPUT_FILE_PREFIX: &str = "output-file-";
-#[derive(Debug, Deserialize, Serialize)]
-pub(crate) struct InputFile {
- pub(crate) url: Url,
- pub(crate) hash: String,
- pub(crate) crypto_info: TeaclaveFileCryptoInfo,
- pub(crate) owner: String,
- pub(crate) data_id: String,
-}
-
-impl InputFile {
- pub(crate) fn new(
- url: Url,
- hash: String,
- crypto_info: TeaclaveFileCryptoInfo,
- owner: String,
- ) -> InputFile {
- let data_id = format!("{}{}", INPUT_FILE_PREFIX,
Uuid::new_v4().to_string());
- InputFile {
- url,
- hash,
- crypto_info,
- owner,
- data_id,
- }
- }
-
- pub(crate) fn from_slice(bytes: &[u8]) -> Result<Self> {
- let ret: InputFile =
- serde_json::from_slice(&bytes).map_err(|_| anyhow!("failed to
Deserialize"))?;
- Ok(ret)
- }
-
- pub(crate) fn to_vec(&self) -> Result<Vec<u8>> {
- serde_json::to_vec(&self).map_err(|_| anyhow!("failed to Serialize"))
- }
-
- pub(crate) fn get_key_vec(&self) -> Vec<u8> {
- self.data_id.as_bytes().to_vec()
- }
-
- pub(crate) fn is_input_file_id(id: &str) -> bool {
- id.starts_with(INPUT_FILE_PREFIX)
- }
-}
-
-#[derive(Debug, Deserialize, Serialize)]
-pub(crate) struct OutputFile {
- pub(crate) url: Url,
- pub(crate) hash: Option<String>,
- pub(crate) crypto_info: TeaclaveFileCryptoInfo,
- pub(crate) owner: String,
- pub(crate) data_id: String,
-}
-
-impl OutputFile {
- pub(crate) fn new(url: Url, crypto_info: TeaclaveFileCryptoInfo, owner:
String) -> OutputFile {
- let data_id = format!("{}{}", OUTPUT_FILE_PREFIX,
Uuid::new_v4().to_string());
- OutputFile {
- url,
- hash: None,
- crypto_info,
- owner,
- data_id,
- }
- }
-
- pub(crate) fn from_slice(bytes: &[u8]) -> Result<Self> {
- serde_json::from_slice(&bytes).map_err(|_| anyhow!("failed to
Deserialize"))
- }
-
- pub(crate) fn to_vec(&self) -> Result<Vec<u8>> {
- serde_json::to_vec(&self).map_err(|_| anyhow!("failed to Serialize"))
- }
-
- pub(crate) fn get_key_vec(&self) -> Vec<u8> {
- self.data_id.as_bytes().to_vec()
- }
-
- pub(crate) fn is_output_file_id(id: &str) -> bool {
- id.starts_with(OUTPUT_FILE_PREFIX)
- }
-}
diff --git a/services/management/enclave/src/function.rs
b/services/management/enclave/src/function.rs
deleted file mode 100644
index 4c7834e..0000000
--- a/services/management/enclave/src/function.rs
+++ /dev/null
@@ -1,79 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements. See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership. The ASF licenses this file
-// to you 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.
-use anyhow::{anyhow, Result};
-use serde::{Deserialize, Serialize};
-use serde_json;
-use std::prelude::v1::*;
-use teaclave_proto::teaclave_frontend_service::{
- FunctionInput, FunctionOutput, RegisterFunctionRequest,
-};
-
-use uuid::Uuid;
-const SCRIPT_PREFIX: &str = "function-";
-const NATIVE_PREFIX: &str = "native-";
-#[derive(Debug, Deserialize, Serialize)]
-pub(crate) struct Function {
- pub(crate) function_id: String,
- pub(crate) name: String,
- pub(crate) description: String,
- pub(crate) payload: Vec<u8>,
- pub(crate) is_public: bool,
- pub(crate) arg_list: Vec<String>,
- pub(crate) input_list: Vec<FunctionInput>,
- pub(crate) output_list: Vec<FunctionOutput>,
- pub(crate) owner: String,
- pub(crate) is_native: bool,
-}
-
-impl Function {
- pub(crate) fn new_from_register_request(
- request: RegisterFunctionRequest,
- owner: String,
- ) -> Function {
- let function_id = format!("{}{}", SCRIPT_PREFIX,
Uuid::new_v4().to_string());
- Function {
- function_id,
- name: request.name,
- description: request.description,
- payload: request.payload,
- is_public: request.is_public,
- arg_list: request.arg_list,
- input_list: request.input_list,
- output_list: request.output_list,
- owner,
- is_native: false,
- }
- }
-
- pub(crate) fn from_slice(bytes: &[u8]) -> Result<Self> {
- let ret: Function =
- serde_json::from_slice(&bytes).map_err(|_| anyhow!("failed to
Deserialize"))?;
- Ok(ret)
- }
-
- pub(crate) fn to_vec(&self) -> Result<Vec<u8>> {
- serde_json::to_vec(&self).map_err(|_| anyhow!("failed to Serialize"))
- }
-
- pub(crate) fn get_key_vec(&self) -> Vec<u8> {
- self.function_id.as_bytes().to_vec()
- }
-
- pub(crate) fn is_function_id(id: &str) -> bool {
- id.starts_with(NATIVE_PREFIX) || id.starts_with(SCRIPT_PREFIX)
- }
-}
diff --git a/services/management/enclave/src/fusion_data.rs
b/services/management/enclave/src/fusion_data.rs
deleted file mode 100644
index ad1216f..0000000
--- a/services/management/enclave/src/fusion_data.rs
+++ /dev/null
@@ -1,70 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements. See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership. The ASF licenses this file
-// to you 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.
-use anyhow::{anyhow, Result};
-use serde::{Deserialize, Serialize};
-use serde_json;
-use std::prelude::v1::*;
-use teaclave_types::TeaclaveFileCryptoInfo;
-use url::Url;
-use uuid::Uuid;
-
-const FUSION_DATA_PREFIX: &str = "fusion-data-";
-#[derive(Debug, Deserialize, Serialize)]
-pub(crate) struct FusionData {
- pub(crate) url: Url,
- pub(crate) hash: Option<String>,
- pub(crate) crypto_info: TeaclaveFileCryptoInfo,
- pub(crate) data_owner_id_list: Vec<String>,
- pub(crate) data_id: String,
-}
-
-fn gen_url_for_fusion_data(data_id: &str) -> Result<Url> {
- let url = format!("fusion://path/{}?token=fusion_token", data_id);
- info!("{}", url);
- Url::parse(&url).map_err(|_| anyhow!("invalid url"))
-}
-
-impl FusionData {
- pub fn new(data_owner_id_list: Vec<String>) -> Result<Self> {
- let data_id = format!("{}{}", FUSION_DATA_PREFIX,
Uuid::new_v4().to_string());
- let url = gen_url_for_fusion_data(&data_id)?;
- let crypto_info = TeaclaveFileCryptoInfo::default();
- Ok(FusionData {
- url,
- hash: None,
- crypto_info,
- data_owner_id_list,
- data_id,
- })
- }
-
- pub(crate) fn from_slice(bytes: &[u8]) -> Result<Self> {
- serde_json::from_slice(&bytes).map_err(|_| anyhow!("failed to
Deserialize"))
- }
-
- pub(crate) fn to_vec(&self) -> Result<Vec<u8>> {
- serde_json::to_vec(&self).map_err(|_| anyhow!("failed to Serialize"))
- }
-
- pub(crate) fn get_key_vec(&self) -> Vec<u8> {
- self.data_id.as_bytes().to_vec()
- }
-
- pub(crate) fn is_fusion_data_id(id: &str) -> bool {
- id.starts_with(FUSION_DATA_PREFIX)
- }
-}
diff --git a/services/management/enclave/src/lib.rs
b/services/management/enclave/src/lib.rs
index 2d9fbcc..5a8d8cd 100644
--- a/services/management/enclave/src/lib.rs
+++ b/services/management/enclave/src/lib.rs
@@ -41,8 +41,7 @@ use teaclave_rpc::server::SgxTrustedTlsServer;
use teaclave_service_enclave_utils::ServiceEnclave;
use teaclave_types::{EnclaveInfo, TeeServiceError, TeeServiceResult};
-mod function;
-mod fusion_data;
+//mod fusion_data;
mod service;
mod task;
@@ -161,7 +160,6 @@ pub mod tests {
run_tests!(
service::tests::handle_input_file,
service::tests::handle_output_file,
- service::tests::handle_fusion_data,
service::tests::handle_function,
service::tests::handle_task,
service::tests::handle_staged_task,
diff --git a/services/management/enclave/src/service.rs
b/services/management/enclave/src/service.rs
index 0d8a9b7..074a1b1 100644
--- a/services/management/enclave/src/service.rs
+++ b/services/management/enclave/src/service.rs
@@ -1,17 +1,21 @@
-use crate::function::Function;
-use crate::fusion_data::FusionData;
-use crate::task::{InputData, OutputData, StagedTask, Task};
+use crate::task::{
+ assign_input_to_task, assign_output_to_task,
try_update_task_to_approved_status,
+ try_update_task_to_ready_status,
+};
use anyhow::{anyhow, Result};
use std::collections::HashMap;
+use std::collections::HashSet;
use std::prelude::v1::*;
use std::sync::{Arc, SgxMutex as Mutex};
use teaclave_proto::teaclave_frontend_service::{
ApproveTaskRequest, ApproveTaskResponse, AssignDataRequest,
AssignDataResponse,
CreateTaskRequest, CreateTaskResponse, GetFunctionRequest,
GetFunctionResponse,
- GetFusionDataRequest, GetFusionDataResponse, GetOutputFileRequest,
GetOutputFileResponse,
+ GetInputFileRequest, GetInputFileResponse, GetOutputFileRequest,
GetOutputFileResponse,
GetTaskRequest, GetTaskResponse, InvokeTaskRequest, InvokeTaskResponse,
- RegisterFunctionRequest, RegisterFunctionResponse,
RegisterInputFileRequest,
- RegisterInputFileResponse, RegisterOutputFileRequest,
RegisterOutputFileResponse, TaskStatus,
+ RegisterFunctionRequest, RegisterFunctionResponse,
RegisterFusionOutputRequest,
+ RegisterFusionOutputResponse, RegisterInputFileRequest,
RegisterInputFileResponse,
+ RegisterInputFromOutputRequest, RegisterInputFromOutputResponse,
RegisterOutputFileRequest,
+ RegisterOutputFileResponse,
};
use teaclave_proto::teaclave_management_service::TeaclaveManagement;
use teaclave_proto::teaclave_storage_service::{
@@ -20,13 +24,13 @@ use teaclave_proto::teaclave_storage_service::{
use teaclave_rpc::endpoint::Endpoint;
use teaclave_rpc::Request;
use teaclave_service_enclave_utils::teaclave_service;
+use teaclave_types::{Function, FunctionInput, FunctionOutput};
+use teaclave_types::{InputData, OutputData, StagedTask, Task, TaskStatus};
use teaclave_types::{Storable, TeaclaveInputFile, TeaclaveOutputFile};
use teaclave_types::{TeaclaveServiceResponseError,
TeaclaveServiceResponseResult};
use thiserror::Error;
#[cfg(test_mode)]
-use core::str::FromStr;
-#[cfg(test_mode)]
use uuid::Uuid;
#[derive(Error, Debug)]
@@ -72,8 +76,10 @@ impl TeaclaveManagement for TeaclaveManagementService {
.to_string();
let request = request.message;
+ let mut owner_list = HashSet::new();
+ owner_list.insert(user_id);
let input_file =
- TeaclaveInputFile::new(request.url, request.hash,
request.crypto_info, user_id);
+ TeaclaveInputFile::new(request.url, request.hash,
request.crypto_info, owner_list);
self.write_to_db(&input_file)
.map_err(|_| TeaclaveManagementError::StorageError)?;
let response = RegisterInputFileResponse {
@@ -94,7 +100,9 @@ impl TeaclaveManagement for TeaclaveManagementService {
.to_string();
let request = request.message;
- let output_file = TeaclaveOutputFile::new(request.url,
request.crypto_info, user_id);
+ let mut owner_list = HashSet::new();
+ owner_list.insert(user_id);
+ let output_file = TeaclaveOutputFile::new(request.url,
request.crypto_info, owner_list);
self.write_to_db(&output_file)
.map_err(|_| TeaclaveManagementError::StorageError)?;
let response = RegisterOutputFileResponse {
@@ -103,7 +111,65 @@ impl TeaclaveManagement for TeaclaveManagementService {
Ok(response)
}
- // access control: output_file.owner == user_id
+ // access control: user_id in owner_list
+ fn register_fusion_output(
+ &self,
+ request: Request<RegisterFusionOutputRequest>,
+ ) -> TeaclaveServiceResponseResult<RegisterFusionOutputResponse> {
+ let user_id = request
+ .metadata
+ .get("id")
+ .ok_or_else(|| TeaclaveManagementError::InvalidRequest)?
+ .to_string();
+
+ let owner_list = request.message.owner_list;
+ if !owner_list.contains(&user_id) {
+ return Err(TeaclaveManagementError::PermissionDenied.into());
+ }
+
+ let output_file = TeaclaveOutputFile::new_fusion_data(owner_list)
+ .map_err(|_| TeaclaveManagementError::DataError)?;
+ self.write_to_db(&output_file)
+ .map_err(|_| TeaclaveManagementError::StorageError)?;
+ let response = RegisterFusionOutputResponse {
+ data_id: output_file.external_id(),
+ };
+ Ok(response)
+ }
+
+ // access control:
+ // 1) user_id in output.owner
+ // 2) hash != none
+ fn register_input_from_output(
+ &self,
+ request: Request<RegisterInputFromOutputRequest>,
+ ) -> TeaclaveServiceResponseResult<RegisterInputFromOutputResponse> {
+ let user_id = request
+ .metadata
+ .get("id")
+ .ok_or_else(|| TeaclaveManagementError::InvalidRequest)?
+ .to_string();
+ if !TeaclaveOutputFile::match_prefix(&request.message.data_id) {
+ return Err(TeaclaveManagementError::PermissionDenied.into());
+ }
+ let output: TeaclaveOutputFile = self
+ .read_from_db(request.message.data_id.as_bytes())
+ .map_err(|_| TeaclaveManagementError::PermissionDenied)?;
+ if !output.owner.contains(&user_id) {
+ return Err(TeaclaveManagementError::PermissionDenied.into());
+ }
+
+ let input = TeaclaveInputFile::from_output(output)
+ .map_err(|_| TeaclaveManagementError::PermissionDenied)?;
+ self.write_to_db(&input)
+ .map_err(|_| TeaclaveManagementError::StorageError)?;
+ let response = RegisterInputFromOutputResponse {
+ data_id: input.external_id(),
+ };
+ Ok(response)
+ }
+
+ // access control: output_file.owner contains user_id
fn get_output_file(
&self,
request: Request<GetOutputFileRequest>,
@@ -122,32 +188,41 @@ impl TeaclaveManagement for TeaclaveManagementService {
.read_from_db(&request.message.data_id.as_bytes())
.map_err(|_| TeaclaveManagementError::PermissionDenied)?;
- if output_file.owner != user_id {
+ if !output_file.owner.contains(&user_id) {
return Err(TeaclaveManagementError::PermissionDenied.into());
}
let response = GetOutputFileResponse {
+ owner: output_file.owner,
hash: output_file.hash.unwrap_or_else(|| "".to_string()),
};
Ok(response)
}
- // access control: fusion_data.data_owner_id_list.contains(user_id)
- fn get_fusion_data(
+ // access control: input_file.owner contains user_id
+ fn get_input_file(
&self,
- request: Request<GetFusionDataRequest>,
- ) -> TeaclaveServiceResponseResult<GetFusionDataResponse> {
+ request: Request<GetInputFileRequest>,
+ ) -> TeaclaveServiceResponseResult<GetInputFileResponse> {
let user_id = request
.metadata
.get("id")
.ok_or_else(|| TeaclaveManagementError::InvalidRequest)?
.to_string();
- let fusion_data =
self.get_fusion_data_from_storage(&request.message.data_id)?;
- if !fusion_data.data_owner_id_list.contains(&user_id) {
+
+ if !TeaclaveInputFile::match_prefix(&request.message.data_id) {
+ return Err(TeaclaveManagementError::PermissionDenied.into());
+ }
+
+ let input_file: TeaclaveInputFile = self
+ .read_from_db(&request.message.data_id.as_bytes())
+ .map_err(|_| TeaclaveManagementError::PermissionDenied)?;
+
+ if !input_file.owner.contains(&user_id) {
return Err(TeaclaveManagementError::PermissionDenied.into());
}
- let response = GetFusionDataResponse {
- hash: fusion_data.hash.unwrap_or_else(|| "".to_string()),
- data_owner_id_list: fusion_data.data_owner_id_list,
+ let response = GetInputFileResponse {
+ owner: input_file.owner,
+ hash: input_file.hash,
};
Ok(response)
}
@@ -164,16 +239,24 @@ impl TeaclaveManagement for TeaclaveManagementService {
.to_string();
let request = request.message;
- let function = Function::new_from_register_request(request, user_id);
- let key = function.get_key_vec();
- let value = function
- .to_vec()
- .map_err(|_| TeaclaveManagementError::DataError)?;
+ let function_id = Uuid::new_v4();
+ let function = Function {
+ function_id,
+ name: request.name,
+ description: request.description,
+ payload: request.payload,
+ is_public: request.is_public,
+ arg_list: request.arg_list,
+ input_list: request.input_list,
+ output_list: request.output_list,
+ owner: user_id,
+ is_native: false,
+ };
- self.write_to_storage(&key, &value)
+ self.write_to_db(&function)
.map_err(|_| TeaclaveManagementError::StorageError)?;
let response = RegisterFunctionResponse {
- function_id: function.function_id,
+ function_id: function.external_id(),
};
Ok(response)
}
@@ -188,7 +271,13 @@ impl TeaclaveManagement for TeaclaveManagementService {
.get("id")
.ok_or_else(|| TeaclaveManagementError::InvalidRequest)?
.to_string();
- let function =
self.get_function_from_storage(&request.message.function_id)?;
+ if !Function::match_prefix(&request.message.function_id) {
+ return Err(TeaclaveManagementError::PermissionDenied.into());
+ }
+
+ let function: Function = self
+ .read_from_db(request.message.function_id.as_bytes())
+ .map_err(|_| TeaclaveManagementError::PermissionDenied)?;
if !(function.is_public || function.owner == user_id) {
return Err(TeaclaveManagementError::PermissionDenied.into());
}
@@ -220,8 +309,10 @@ impl TeaclaveManagement for TeaclaveManagementService {
.ok_or_else(|| TeaclaveManagementError::InvalidRequest)?
.to_string();
let request = request.message;
- let function = self.get_function_from_storage(&request.function_id)?;
- let mut task = Task::new(
+ let function: Function = self
+ .read_from_db(request.function_id.as_bytes())
+ .map_err(|_| TeaclaveManagementError::PermissionDenied)?;
+ let task = crate::task::create_task(
function,
user_id,
request.arg_list,
@@ -229,19 +320,10 @@ impl TeaclaveManagement for TeaclaveManagementService {
request.output_data_owner_list,
)
.map_err(|_| TeaclaveManagementError::BadTask)?;
- // register fusion data
- for (output_name, data_owner_id_list) in
task.output_data_owner_list.iter() {
- if data_owner_id_list.user_id_list.len() > 1 {
- let user_id_list: Vec<String> =
- data_owner_id_list.user_id_list.iter().cloned().collect();
- let fusion_data = self.alloc_fusion_data(user_id_list)?;
- task.output_map
- .insert(output_name.to_string(), fusion_data.data_id);
- }
- }
- self.insert_or_update_task_to_storage(&task)?;
+ self.write_to_db(&task)
+ .map_err(|_| TeaclaveManagementError::StorageError)?;
Ok(CreateTaskResponse {
- task_id: task.task_id,
+ task_id: task.external_id(),
})
}
@@ -255,12 +337,18 @@ impl TeaclaveManagement for TeaclaveManagementService {
.get("id")
.ok_or_else(|| TeaclaveManagementError::InvalidRequest)?
.to_string();
- let task: Task = self.get_task_from_storage(&request.message.task_id)?;
+
+ if !Task::match_prefix(&request.message.task_id) {
+ return Err(TeaclaveManagementError::PermissionDenied.into());
+ }
+ let task: Task = self
+ .read_from_db(request.message.task_id.as_bytes())
+ .map_err(|_| TeaclaveManagementError::PermissionDenied)?;
if !task.participants.contains(&user_id) {
return Err(TeaclaveManagementError::PermissionDenied.into());
}
let response = GetTaskResponse {
- task_id: task.task_id,
+ task_id: task.external_id(),
creator: task.creator,
function_id: task.function_id,
function_owner: task.function_owner,
@@ -280,14 +368,12 @@ impl TeaclaveManagement for TeaclaveManagementService {
// 1) task.participants.contains(user_id)
// 2) task.status == Created
// 3) user can use the data:
- // * input file: user_id == input_file.owner
- // * output file: user_id == output_file.owner &&
output_file.hash.is_none()
- // * fusion_data: fusion_data.owner_id_list.contains(user_id)
+ // * input file: user_id == input_file.owner contains user_id
+ // * output file: output_file.owner contains user_id &&
output_file.hash.is_none()
// 4) the data can be assgined to the task:
// * input_data_owner_list or output_data_owner_list contains the data
name
- // * input file: DataOwnerList has one user and user == user_id
- // * output file: DataOwnerList has one user and user == user_id
- // * fusion data: not output and DataOwnerList ==
fusion_data.owner_id_list
+ // * input file: DataOwnerList match input_file.owner
+ // * output file: DataOwnerList match output_file.owner
fn assign_data(
&self,
request: Request<AssignDataRequest>,
@@ -298,7 +384,13 @@ impl TeaclaveManagement for TeaclaveManagementService {
.ok_or_else(|| TeaclaveManagementError::InvalidRequest)?
.to_string();
let request = request.message;
- let mut task: Task = self.get_task_from_storage(&request.task_id)?;
+ if !Task::match_prefix(&request.task_id) {
+ return Err(TeaclaveManagementError::PermissionDenied.into());
+ }
+ let mut task: Task = self
+ .read_from_db(request.task_id.as_bytes())
+ .map_err(|_| TeaclaveManagementError::PermissionDenied)?;
+
if !task.participants.contains(&user_id) {
return Err(TeaclaveManagementError::PermissionDenied.into());
}
@@ -311,11 +403,7 @@ impl TeaclaveManagement for TeaclaveManagementService {
let input_file: TeaclaveInputFile = self
.read_from_db(data_id.as_bytes())
.map_err(|_| TeaclaveManagementError::PermissionDenied)?;
- task.assign_input_file(data_name, &input_file, &user_id)
- .map_err(|_| TeaclaveManagementError::PermissionDenied)?;
- } else if FusionData::is_fusion_data_id(data_id) {
- let fusion_data = self.get_fusion_data_from_storage(data_id)?;
- task.assign_fusion_data(data_name, &fusion_data, &user_id)
+ assign_input_to_task(&mut task, data_name, &input_file,
&user_id)
.map_err(|_| TeaclaveManagementError::PermissionDenied)?;
} else {
return Err(TeaclaveManagementError::PermissionDenied.into());
@@ -326,14 +414,15 @@ impl TeaclaveManagement for TeaclaveManagementService {
let output_file: TeaclaveOutputFile = self
.read_from_db(data_id.as_bytes())
.map_err(|_| TeaclaveManagementError::PermissionDenied)?;
- task.assign_output_file(data_name, &output_file, &user_id)
+ assign_output_to_task(&mut task, data_name, &output_file,
&user_id)
.map_err(|_| TeaclaveManagementError::PermissionDenied)?;
} else {
return Err(TeaclaveManagementError::PermissionDenied.into());
}
}
- task.try_update_to_ready_status();
- self.insert_or_update_task_to_storage(&task)?;
+ try_update_task_to_ready_status(&mut task);
+ self.write_to_db(&task)
+ .map_err(|_| TeaclaveManagementError::StorageError)?;
Ok(AssignDataResponse)
}
@@ -350,7 +439,13 @@ impl TeaclaveManagement for TeaclaveManagementService {
.ok_or_else(|| TeaclaveManagementError::InvalidRequest)?
.to_string();
let request = request.message;
- let mut task: Task = self.get_task_from_storage(&request.task_id)?;
+ if !Task::match_prefix(&request.task_id) {
+ return Err(TeaclaveManagementError::PermissionDenied.into());
+ }
+ let mut task: Task = self
+ .read_from_db(request.task_id.as_bytes())
+ .map_err(|_| TeaclaveManagementError::PermissionDenied)?;
+
if !task.participants.contains(&user_id) {
return Err(TeaclaveManagementError::PermissionDenied.into());
}
@@ -359,8 +454,9 @@ impl TeaclaveManagement for TeaclaveManagementService {
_ => return Err(TeaclaveManagementError::PermissionDenied.into()),
}
task.approved_user_list.insert(user_id);
- task.try_update_to_approved_status();
- self.insert_or_update_task_to_storage(&task)?;
+ try_update_task_to_approved_status(&mut task);
+ self.write_to_db(&task)
+ .map_err(|_| TeaclaveManagementError::StorageError)?;
Ok(ApproveTaskResponse)
}
@@ -377,7 +473,13 @@ impl TeaclaveManagement for TeaclaveManagementService {
.ok_or_else(|| TeaclaveManagementError::InvalidRequest)?
.to_string();
let request = request.message;
- let mut task: Task = self.get_task_from_storage(&request.task_id)?;
+ if !Task::match_prefix(&request.task_id) {
+ return Err(TeaclaveManagementError::PermissionDenied.into());
+ }
+ let mut task: Task = self
+ .read_from_db(request.task_id.as_bytes())
+ .map_err(|_| TeaclaveManagementError::PermissionDenied)?;
+
if task.creator != user_id {
return Err(TeaclaveManagementError::PermissionDenied.into());
}
@@ -385,21 +487,22 @@ impl TeaclaveManagement for TeaclaveManagementService {
TaskStatus::Approved => {}
_ => return Err(TeaclaveManagementError::PermissionDenied.into()),
}
- let function = self.get_function_from_storage(&task.function_id)?;
+ if !Function::match_prefix(&task.function_id) {
+ return Err(TeaclaveManagementError::PermissionDenied.into());
+ }
+ let function: Function = self
+ .read_from_db(task.function_id.as_bytes())
+ .map_err(|_| TeaclaveManagementError::PermissionDenied)?;
+
let arg_list: HashMap<String, String> = task.arg_list.clone();
- let mut input_map = HashMap::new();
- let mut output_map = HashMap::new();
+ let mut input_map: HashMap<String, InputData> = HashMap::new();
+ let mut output_map: HashMap<String, OutputData> = HashMap::new();
for (data_name, data_id) in task.input_map.iter() {
- let input_data = if TeaclaveInputFile::match_prefix(data_id) {
+ let input_data: InputData = if
TeaclaveInputFile::match_prefix(data_id) {
let input_file: TeaclaveInputFile = self
.read_from_db(data_id.as_bytes())
.map_err(|_| TeaclaveManagementError::PermissionDenied)?;
InputData::from_input_file(input_file)
- .map_err(|_| TeaclaveManagementError::PermissionDenied)?
- } else if FusionData::is_fusion_data_id(data_id) {
- let fusion_data = self.get_fusion_data_from_storage(data_id)?;
- InputData::from_fusion_data(fusion_data)
- .map_err(|_| TeaclaveManagementError::PermissionDenied)?
} else {
return Err(TeaclaveManagementError::PermissionDenied.into());
};
@@ -407,26 +510,31 @@ impl TeaclaveManagement for TeaclaveManagementService {
}
for (data_name, data_id) in task.output_map.iter() {
- let output_data = if TeaclaveOutputFile::match_prefix(data_id) {
+ let output_data: OutputData = if
TeaclaveOutputFile::match_prefix(data_id) {
let output_file: TeaclaveOutputFile = self
.read_from_db(data_id.as_bytes())
.map_err(|_| TeaclaveManagementError::PermissionDenied)?;
+ if output_file.hash.is_some() {
+ return
Err(TeaclaveManagementError::PermissionDenied.into());
+ }
OutputData::from_output_file(output_file)
- .map_err(|_| TeaclaveManagementError::PermissionDenied)?
- } else if FusionData::is_fusion_data_id(data_id) {
- let fusion_data = self.get_fusion_data_from_storage(data_id)?;
- OutputData::from_fusion_data(fusion_data)
- .map_err(|_| TeaclaveManagementError::PermissionDenied)?
} else {
return Err(TeaclaveManagementError::PermissionDenied.into());
};
output_map.insert(data_name.to_string(), output_data);
}
- let staged_task = StagedTask::new(&task.task_id, function, arg_list,
input_map, output_map);
- self.enqueue_staged_task(&staged_task)?;
+ let staged_task = StagedTask::new(
+ task.task_id.to_owned(),
+ function,
+ arg_list,
+ input_map,
+ output_map,
+ );
+ self.enqueue_to_db(StagedTask::get_queue_key().as_bytes(),
&staged_task)?;
task.status = TaskStatus::Running;
- self.insert_or_update_task_to_storage(&task)?;
+ self.write_to_db(&task)
+ .map_err(|_| TeaclaveManagementError::StorageError)?;
Ok(InvokeTaskResponse)
}
}
@@ -434,30 +542,24 @@ impl TeaclaveManagement for TeaclaveManagementService {
impl TeaclaveManagementService {
#[cfg(test_mode)]
fn add_mock_data(&self) -> Result<()> {
- use teaclave_proto::teaclave_frontend_service::{FunctionInput,
FunctionOutput};
- use teaclave_types::TeaclaveFileCryptoInfo;
- use url::Url;
- let mut fusion_data =
- FusionData::new(vec!["mock_user2".to_string(),
"mock_user3".to_string()])?;
- fusion_data.data_id = "fusion-data-mock-data".to_string();
- fusion_data.hash = Some("deadbeef".to_string());
- let key = fusion_data.get_key_vec();
- let value = fusion_data.to_vec()?;
- self.write_to_storage(&key, &value)?;
-
- let mut fusion_data =
- FusionData::new(vec!["mock_user1".to_string(),
"mock_user2".to_string()])?;
- fusion_data.data_id = "fusion-data-mock-data2".to_string();
- let key = fusion_data.get_key_vec();
- let value = fusion_data.to_vec()?;
- self.write_to_storage(&key, &value)?;
-
- let mut fusion_data =
- FusionData::new(vec!["frontend_user".to_string(),
"mock_user".to_string()])?;
- fusion_data.data_id = "fusion-data-mock-frontend-data".to_string();
- let key = fusion_data.get_key_vec();
- let value = fusion_data.to_vec()?;
- self.write_to_storage(&key, &value)?;
+ let mut owner = HashSet::new();
+ owner.insert("mock_user1".to_string());
+ owner.insert("frontend_user".to_string());
+ let mut output_file = TeaclaveOutputFile::new_fusion_data(owner)?;
+ output_file.uuid =
Uuid::parse_str("00000000-0000-0000-0000-000000000001")?;
+ output_file.hash = Some("deadbeef".to_string());
+ self.write_to_db(&output_file)?;
+
+ let mut owner = HashSet::new();
+ owner.insert("mock_user2".to_string());
+ owner.insert("mock_user3".to_string());
+ let mut output_file = TeaclaveOutputFile::new_fusion_data(owner)?;
+ output_file.uuid =
Uuid::parse_str("00000000-0000-0000-0000-000000000002")?;
+ output_file.hash = Some("deadbeef".to_string());
+ self.write_to_db(&output_file)?;
+ let mut input_file = TeaclaveInputFile::from_output(output_file)?;
+ input_file.uuid =
Uuid::parse_str("00000000-0000-0000-0000-000000000002")?;
+ self.write_to_db(&input_file)?;
let function_input = FunctionInput {
name: "input".to_string(),
@@ -477,7 +579,7 @@ impl TeaclaveManagementService {
};
let native_function = Function {
- function_id: "native-mock-native-func".to_string(),
+ function_id:
Uuid::parse_str("00000000-0000-0000-0000-000000000001")?,
name: "mock-native-func".to_string(),
description: "mock-desc".to_string(),
payload: b"mock-payload".to_vec(),
@@ -488,16 +590,15 @@ impl TeaclaveManagementService {
owner: "teaclave".to_string(),
is_native: true,
};
- let key = native_function.get_key_vec();
- let value = native_function.to_vec()?;
- self.write_to_storage(&key, &value)?;
+
+ self.write_to_db(&native_function)?;
let function_output = FunctionOutput {
name: "output".to_string(),
description: "output_desc".to_string(),
};
let native_function = Function {
- function_id: "native-mock-simple-func".to_string(),
+ function_id:
Uuid::parse_str("00000000-0000-0000-0000-000000000002")?,
name: "mock-native-func".to_string(),
description: "mock-desc".to_string(),
payload: b"mock-payload".to_vec(),
@@ -508,17 +609,7 @@ impl TeaclaveManagementService {
owner: "teaclave".to_string(),
is_native: true,
};
- let key = native_function.get_key_vec();
- let value = native_function.to_vec()?;
- self.write_to_storage(&key, &value)?;
-
- let url = Url::parse("s3://bucket_id/path?token=mock_token").unwrap();
- let user_id = "mock_user1".to_string();
- let crypto_info = TeaclaveFileCryptoInfo::default();
- let mut output_file = TeaclaveOutputFile::new(url, crypto_info,
user_id);
- output_file.hash = Some("deadbeef".to_string());
- output_file.uuid =
Uuid::from_str("00000000-0000-0000-0000-000000000001")?;
- self.write_to_db(&output_file)?;
+ self.write_to_db(&native_function)?;
Ok(())
}
@@ -542,17 +633,6 @@ impl TeaclaveManagementService {
Ok(service)
}
- fn write_to_storage(&self, key: &[u8], value: &[u8]) -> Result<()> {
- let put_request = PutRequest::new(key, value);
- let _put_response = self
- .storage_client
- .clone()
- .lock()
- .map_err(|_| anyhow!("Cannot lock storage client"))?
- .put(put_request)?;
- Ok(())
- }
-
fn write_to_db(&self, item: &impl Storable) -> Result<()> {
let k = item.key();
let v = item.to_vec()?;
@@ -577,87 +657,8 @@ impl TeaclaveManagementService {
T::from_slice(get_response.value.as_slice())
}
- fn read_from_storage(&self, key: &[u8]) -> Result<Vec<u8>> {
- let get_request = GetRequest::new(key);
- let get_response = self
- .storage_client
- .clone()
- .lock()
- .map_err(|_| anyhow!("Cannot lock storage client"))?
- .get(get_request)?;
- Ok(get_response.value)
- }
-
- // avoid accessing other kinds of data: 1) check function_id 2)
deserialization
- fn get_function_from_storage(
- &self,
- function_id: &str,
- ) -> TeaclaveServiceResponseResult<Function> {
- if !Function::is_function_id(function_id) {
- return Err(TeaclaveManagementError::PermissionDenied.into());
- }
- let function_key = function_id.as_bytes();
- let function_bytes = self
- .read_from_storage(function_key)
- .map_err(|_| TeaclaveManagementError::StorageError)?;
- Function::from_slice(&function_bytes).map_err(|_|
TeaclaveManagementError::DataError.into())
- }
-
- fn alloc_fusion_data(
- &self,
- user_id_list: Vec<String>,
- ) -> TeaclaveServiceResponseResult<FusionData> {
- let fusion_data =
- FusionData::new(user_id_list).map_err(|_|
TeaclaveManagementError::DataError)?;
- let data_key = fusion_data.get_key_vec();
- let value = fusion_data
- .to_vec()
- .map_err(|_| TeaclaveManagementError::DataError)?;
- self.write_to_storage(&data_key, &value)
- .map_err(|_| TeaclaveManagementError::StorageError)?;
- Ok(fusion_data)
- }
-
- // avoid accessing other kinds of data: 1) check task_id 2) deserialization
- fn get_task_from_storage(&self, task_id: &str) ->
TeaclaveServiceResponseResult<Task> {
- if !Task::is_task_id(task_id) {
- return Err(TeaclaveManagementError::PermissionDenied.into());
- }
- let task_key = task_id.as_bytes();
- let task_bytes = self
- .read_from_storage(task_key)
- .map_err(|_| TeaclaveManagementError::StorageError)?;
- Task::from_slice(&task_bytes).map_err(|_|
TeaclaveManagementError::DataError.into())
- }
-
- // avoid accessing other kinds of data: 1) check fusion_data_id 2)
deserialization
- fn get_fusion_data_from_storage(
- &self,
- fusion_data_id: &str,
- ) -> TeaclaveServiceResponseResult<FusionData> {
- if !FusionData::is_fusion_data_id(&fusion_data_id) {
- return Err(TeaclaveManagementError::PermissionDenied.into());
- }
- let key = fusion_data_id.as_bytes();
- let value = self
- .read_from_storage(key)
- .map_err(|_| TeaclaveManagementError::StorageError)?;
- FusionData::from_slice(&value).map_err(|_|
TeaclaveManagementError::DataError.into())
- }
-
- fn insert_or_update_task_to_storage(&self, task: &Task) ->
TeaclaveServiceResponseResult<()> {
- let key = task.get_key_vec();
- let value = task
- .to_vec()
- .map_err(|_| TeaclaveManagementError::DataError)?;
- self.write_to_storage(&key, &value)
- .map_err(|_| TeaclaveManagementError::StorageError)?;
- Ok(())
- }
-
- fn enqueue_staged_task(&self, staged_task: &StagedTask) ->
TeaclaveServiceResponseResult<()> {
- let key = StagedTask::get_queue_key();
- let value = staged_task
+ fn enqueue_to_db(&self, key: &[u8], item: &impl Storable) ->
TeaclaveServiceResponseResult<()> {
+ let value = item
.to_vec()
.map_err(|_| TeaclaveManagementError::DataError)?;
let enqueue_request = EnqueueRequest::new(key, value);
@@ -674,15 +675,17 @@ impl TeaclaveManagementService {
#[cfg(feature = "enclave_unit_test")]
pub mod tests {
use super::*;
- use std::collections::HashMap;
- use teaclave_proto::teaclave_frontend_service::{FunctionInput,
FunctionOutput};
- use teaclave_types::{TeaclaveFileCryptoInfo, TeaclaveFileRootKey128};
+ use std::collections::{HashMap, HashSet};
+ use teaclave_types::{
+ FunctionInput, FunctionOutput, TeaclaveFileCryptoInfo,
TeaclaveFileRootKey128,
+ };
use url::Url;
pub fn handle_input_file() {
let url = Url::parse("s3://bucket_id/path?token=mock_token").unwrap();
let hash =
"a6d604b5987b693a19d94704532b5d928c2729f24dfd40745f8d03ac9ac75a8b".to_string();
- let user_id = "mock_user".to_string();
+ let mut user_id: HashSet<String> = HashSet::new();
+ user_id.insert("mock_user".to_string());
let crypto_info = TeaclaveFileCryptoInfo::TeaclaveFileRootKey128(
TeaclaveFileRootKey128::new(&[0; 16]).unwrap(),
);
@@ -695,7 +698,8 @@ pub mod tests {
pub fn handle_output_file() {
let url = Url::parse("s3://bucket_id/path?token=mock_token").unwrap();
- let user_id = "mock_user".to_string();
+ let mut user_id: HashSet<String> = HashSet::new();
+ user_id.insert("mock_user".to_string());
let crypto_info = TeaclaveFileCryptoInfo::TeaclaveFileRootKey128(
TeaclaveFileRootKey128::new(&[0; 16]).unwrap(),
);
@@ -706,18 +710,6 @@ pub mod tests {
info!("file: {:?}", deserialized_file);
}
- pub fn handle_fusion_data() {
- let fusion_data =
- FusionData::new(vec!["mock_user_a".to_string(),
"mock_user_b".to_string()]).unwrap();
- let key = fusion_data.get_key_vec();
- let key_str = std::str::from_utf8(&key).unwrap();
- info!("key: {}", key_str);
- assert!(FusionData::is_fusion_data_id(key_str));
- let value = fusion_data.to_vec().unwrap();
- let deserialized_data = FusionData::from_slice(&value).unwrap();
- info!("data: {:?}", deserialized_data);
- }
-
pub fn handle_function() {
let function_input = FunctionInput {
name: "input".to_string(),
@@ -727,7 +719,8 @@ pub mod tests {
name: "output".to_string(),
description: "output_desc".to_string(),
};
- let register_request = RegisterFunctionRequest {
+ let function = Function {
+ function_id: Uuid::new_v4(),
name: "mock_function".to_string(),
description: "mock function".to_string(),
payload: b"python script".to_vec(),
@@ -735,34 +728,32 @@ pub mod tests {
arg_list: vec!["arg".to_string()],
input_list: vec![function_input],
output_list: vec![function_output],
+ owner: "mock_user".to_string(),
+ is_native: false,
};
- let function =
- Function::new_from_register_request(register_request,
"mock_user".to_string());
- let key = function.get_key_vec();
- let key_str = std::str::from_utf8(&key).unwrap();
- info!("key: {}", key_str);
- assert!(Function::is_function_id(key_str));
+ assert!(Function::match_prefix(&function.key_string()));
let value = function.to_vec().unwrap();
- let deserialized_data = Function::from_slice(&value).unwrap();
- info!("data: {:?}", deserialized_data);
+ let deserialized_function = Function::from_slice(&value).unwrap();
+ info!("function: {:?}", deserialized_function);
}
pub fn handle_task() {
- let function_request = RegisterFunctionRequest {
+ let function = Function {
+ function_id: Uuid::new_v4(),
name: "mock_function".to_string(),
description: "mock function".to_string(),
payload: b"python script".to_vec(),
- is_public: false,
+ is_public: true,
arg_list: vec!["arg".to_string()],
input_list: vec![],
output_list: vec![],
+ owner: "mock_user".to_string(),
+ is_native: false,
};
- let function =
- Function::new_from_register_request(function_request,
"mock_user".to_string());
let mut arg_list = HashMap::new();
arg_list.insert("arg".to_string(), "data".to_string());
- let task = Task::new(
+ let task = crate::task::create_task(
function,
"mock_user".to_string(),
arg_list,
@@ -771,18 +762,15 @@ pub mod tests {
)
.unwrap();
- let key = task.get_key_vec();
- let key_str = std::str::from_utf8(&key).unwrap();
- info!("key: {}", key_str);
- assert!(Task::is_task_id(key_str));
+ assert!(Task::match_prefix(&task.key_string()));
let value = task.to_vec().unwrap();
- let deserialized_data = Task::from_slice(&value).unwrap();
- info!("data: {:?}", deserialized_data);
+ let deserialized_task = Task::from_slice(&value).unwrap();
+ info!("task: {:?}", deserialized_task);
}
pub fn handle_staged_task() {
let function = Function {
- function_id: "function-mock".to_string(),
+ function_id: Uuid::new_v4(),
name: "mock".to_string(),
description: "".to_string(),
payload: b"python script".to_vec(),
@@ -812,7 +800,8 @@ pub mod tests {
let mut output_map = HashMap::new();
output_map.insert("output".to_string(), output_data);
- let staged_task = StagedTask::new("task-mock", function, arg_list,
input_map, output_map);
+ let staged_task =
+ StagedTask::new(Uuid::new_v4(), function, arg_list, input_map,
output_map);
let value = staged_task.to_vec().unwrap();
let deserialized_data = StagedTask::from_slice(&value).unwrap();
diff --git a/services/management/enclave/src/task.rs
b/services/management/enclave/src/task.rs
index 9171f49..d6e3729 100644
--- a/services/management/enclave/src/task.rs
+++ b/services/management/enclave/src/task.rs
@@ -14,352 +14,177 @@
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
-use crate::function::Function;
-use crate::fusion_data::FusionData;
use anyhow::{anyhow, ensure, Result};
-use serde::{Deserialize, Serialize};
-use serde_json;
use std::collections::HashMap;
use std::collections::HashSet;
use std::prelude::v1::*;
-use teaclave_proto::teaclave_frontend_service::{DataOwnerList, TaskStatus};
-use teaclave_types::TeaclaveFileCryptoInfo;
-use teaclave_types::{Storable, TeaclaveInputFile, TeaclaveOutputFile};
-use url::Url;
+use teaclave_types::Function;
+use teaclave_types::{
+ DataOwnerList, Storable, Task, TaskStatus, TeaclaveInputFile,
TeaclaveOutputFile,
+};
use uuid::Uuid;
-const TASK_PREFIX: &str = "task-";
-const STAGED_TASK_PREFIX: &str = "staged-"; // staged-task-uuid
-const QUEUE_KEY: &str = "staged-task";
-#[derive(Debug, Deserialize, Serialize)]
-pub(crate) struct Task {
- pub(crate) task_id: String,
- pub(crate) creator: String,
- pub(crate) function_id: String,
- pub(crate) function_owner: String,
- pub(crate) arg_list: HashMap<String, String>,
- pub(crate) input_data_owner_list: HashMap<String, DataOwnerList>,
- pub(crate) output_data_owner_list: HashMap<String, DataOwnerList>,
- pub(crate) participants: HashSet<String>,
- pub(crate) approved_user_list: HashSet<String>,
- pub(crate) input_map: HashMap<String, String>,
- pub(crate) output_map: HashMap<String, String>,
- pub(crate) status: TaskStatus,
+pub(crate) fn create_task(
+ function: Function,
+ creator: String,
+ arg_list: HashMap<String, String>,
+ input_data_owner_list: HashMap<String, DataOwnerList>,
+ output_data_owner_list: HashMap<String, DataOwnerList>,
+) -> Result<Task> {
+ let task_id = Uuid::new_v4();
+ let mut participants = HashSet::new();
+ if !function.is_public {
+ participants.insert(function.owner.clone());
+ }
+ participants.insert(creator.clone());
+ for (_, data_owner_list) in input_data_owner_list.iter() {
+ for user_id in data_owner_list.user_id_list.iter() {
+ participants.insert(user_id.clone());
+ }
+ }
+ for (_, data_owner_list) in output_data_owner_list.iter() {
+ for user_id in data_owner_list.user_id_list.iter() {
+ participants.insert(user_id.clone());
+ }
+ }
+ let task = Task {
+ task_id,
+ creator,
+ function_id: function.external_id(),
+ function_owner: function.owner,
+ arg_list,
+ input_data_owner_list,
+ output_data_owner_list,
+ participants,
+ approved_user_list: HashSet::new(),
+ input_map: HashMap::new(),
+ output_map: HashMap::new(),
+ status: TaskStatus::Created,
+ };
+ // check arguments
+ let function_args: HashSet<String> =
function.arg_list.into_iter().collect();
+ let provide_args: HashSet<String> =
task.arg_list.keys().cloned().collect();
+ let diff: HashSet<_> = function_args.difference(&provide_args).collect();
+ ensure!(diff.is_empty(), "bad arguments");
+
+ // check input
+ let input_args: HashSet<String> = function.input_list.into_iter().map(|f|
f.name).collect();
+ let provide_args: HashSet<String> =
task.input_data_owner_list.keys().cloned().collect();
+ let diff: HashSet<_> = input_args.difference(&provide_args).collect();
+ ensure!(diff.is_empty(), "bad input");
+
+ // check output
+ let output_args: HashSet<String> =
function.output_list.into_iter().map(|f| f.name).collect();
+ let provide_args: HashSet<String> =
task.output_data_owner_list.keys().cloned().collect();
+ let diff: HashSet<_> = output_args.difference(&provide_args).collect();
+ ensure!(diff.is_empty(), "bad output");
+
+ Ok(task)
}
-#[derive(Debug, Deserialize, Serialize)]
-pub(crate) struct InputData {
- pub(crate) url: Url,
- pub(crate) hash: String,
- pub(crate) crypto_info: TeaclaveFileCryptoInfo,
-}
-#[derive(Debug, Deserialize, Serialize)]
-pub(crate) struct OutputData {
- pub(crate) url: Url,
- pub(crate) crypto_info: TeaclaveFileCryptoInfo,
-}
-
-#[derive(Debug, Deserialize, Serialize)]
-pub(crate) struct StagedTask {
- pub(crate) staged_task_id: String,
- pub(crate) task_id: String,
- pub(crate) function_id: String,
- pub(crate) function_payload: Vec<u8>,
- pub(crate) arg_list: HashMap<String, String>,
- pub(crate) input_map: HashMap<String, InputData>,
- pub(crate) output_map: HashMap<String, OutputData>,
-}
-
-impl Task {
- pub(crate) fn new(
- function: Function,
- creator: String,
- arg_list: HashMap<String, String>,
- input_data_owner_list: HashMap<String, DataOwnerList>,
- output_data_owner_list: HashMap<String, DataOwnerList>,
- ) -> Result<Self> {
- let task_id = format!("{}{}", TASK_PREFIX, Uuid::new_v4().to_string());
- let mut participants = HashSet::new();
- if !function.is_public {
- participants.insert(function.owner.clone());
- }
- participants.insert(creator.clone());
- for (_, data_owner_list) in input_data_owner_list.iter() {
- for user_id in data_owner_list.user_id_list.iter() {
- participants.insert(user_id.clone());
- }
- }
- for (_, data_owner_list) in output_data_owner_list.iter() {
- for user_id in data_owner_list.user_id_list.iter() {
- participants.insert(user_id.clone());
+// access control:
+// 1) input_file.owner contains user_id
+// 2) input_data_owner_list contains the data name
+// 3) user_id_list == input_file.owner
+pub(crate) fn assign_input_to_task(
+ task: &mut Task,
+ data_name: &str,
+ file: &TeaclaveInputFile,
+ user_id: &str,
+) -> Result<()> {
+ if !file.owner.contains(&user_id.to_string()) {
+ return Err(anyhow!("no permission"));
+ }
+ match task.input_data_owner_list.get(data_name) {
+ Some(data_owner_list) => {
+ let user_id_list = &data_owner_list.user_id_list;
+ if user_id_list.len() != file.owner.len() {
+ return Err(anyhow!("no permission"));
}
- }
- let task = Self {
- task_id,
- creator,
- function_id: function.function_id,
- function_owner: function.owner,
- arg_list,
- input_data_owner_list,
- output_data_owner_list,
- participants,
- approved_user_list: HashSet::new(),
- input_map: HashMap::new(),
- output_map: HashMap::new(),
- status: TaskStatus::Created,
- };
- // check arguments
- let function_args: HashSet<String> =
function.arg_list.into_iter().collect();
- let provide_args: HashSet<String> =
task.arg_list.keys().cloned().collect();
- let diff: HashSet<_> =
function_args.difference(&provide_args).collect();
- ensure!(diff.is_empty(), "bad arguments");
-
- // check input
- let input_args: HashSet<String> =
function.input_list.into_iter().map(|f| f.name).collect();
- let provide_args: HashSet<String> =
task.input_data_owner_list.keys().cloned().collect();
- let diff: HashSet<_> = input_args.difference(&provide_args).collect();
- ensure!(diff.is_empty(), "bad input");
-
- // check output
- let output_args: HashSet<String> =
- function.output_list.into_iter().map(|f| f.name).collect();
- let provide_args: HashSet<String> =
task.output_data_owner_list.keys().cloned().collect();
- let diff: HashSet<_> = output_args.difference(&provide_args).collect();
- ensure!(diff.is_empty(), "bad output");
-
- Ok(task)
- }
-
- pub(crate) fn from_slice(bytes: &[u8]) -> Result<Self> {
- let ret: Task =
- serde_json::from_slice(&bytes).map_err(|_| anyhow!("failed to
Deserialize"))?;
- Ok(ret)
- }
-
- pub(crate) fn to_vec(&self) -> Result<Vec<u8>> {
- serde_json::to_vec(&self).map_err(|_| anyhow!("failed to Serialize"))
- }
-
- pub(crate) fn get_key_vec(&self) -> Vec<u8> {
- self.task_id.as_bytes().to_vec()
- }
-
- // access control:
- // 1) user_id == input_file.owner
- // 2) input_data_owner_list contains the data name
- // 3) DataOwnerList has only one user
- // 4) user_id_list == user_id
- pub(crate) fn assign_input_file(
- &mut self,
- data_name: &str,
- file: &TeaclaveInputFile,
- user_id: &str,
- ) -> Result<()> {
- if file.owner != user_id {
- return Err(anyhow!("no permission"));
- }
- match self.input_data_owner_list.get(data_name) {
- Some(data_owner_list) => {
- let user_id_list = &data_owner_list.user_id_list;
- if user_id_list.len() != 1 {
- return Err(anyhow!("no permission"));
- }
- if !user_id_list.contains(user_id) {
+ for owner in user_id_list.iter() {
+ if !file.owner.contains(owner) {
return Err(anyhow!("no permission"));
}
}
- None => return Err(anyhow!("no such this input name")),
- };
- self.input_map
- .insert(data_name.to_owned(), file.external_id());
- Ok(())
- }
-
- // access control:
- // 1) output_file is not used.
- // 2) user_id == output_file.owner
- // 3) output_data_owner_list contains the data name
- // 4) DataOwnerList has only one user
- // 5) user_id_list == user_id
- pub(crate) fn assign_output_file(
- &mut self,
- data_name: &str,
- file: &TeaclaveOutputFile,
- user_id: &str,
- ) -> Result<()> {
- if file.hash.is_some() {
- return Err(anyhow!("no permission"));
}
- if file.owner != user_id {
- return Err(anyhow!("no permission"));
- }
- match self.output_data_owner_list.get(data_name) {
- Some(data_owner_list) => {
- let user_id_list = &data_owner_list.user_id_list;
- if user_id_list.len() != 1 {
- return Err(anyhow!("no permission"));
- }
- if !user_id_list.contains(user_id) {
- return Err(anyhow!("no permission"));
- }
- }
- None => return Err(anyhow!("no such this input name")),
- };
- self.output_map
- .insert(data_name.to_owned(), file.external_id());
- Ok(())
- }
+ None => return Err(anyhow!("no such input name")),
+ };
+ task.input_map
+ .insert(data_name.to_owned(), file.external_id());
+ Ok(())
+}
- // access control:
- // 1) fusion_data: fusion_data.owner_id_list.contains(user_id)
- // 2) DataOwnerList == fusion_data.owner_id_list
- // 3) input_data_owner_list contains the data name
- pub(crate) fn assign_fusion_data(
- &mut self,
- data_name: &str,
- fusion_data: &FusionData,
- user_id: &str,
- ) -> Result<()> {
- if !fusion_data
- .data_owner_id_list
- .contains(&user_id.to_string())
- {
- return Err(anyhow!("no permission"));
- }
- match self.input_data_owner_list.get(data_name) {
- Some(data_owner_list) => {
- let user_id_list = &data_owner_list.user_id_list;
- if user_id_list.len() != fusion_data.data_owner_id_list.len() {
+// access control:
+// 1) output_file is not used.
+// 2) output_file.owner contains user_id
+// 3) output_data_owner_list contains the data name
+// 4) user_id_list == output_file.owner
+pub(crate) fn assign_output_to_task(
+ task: &mut Task,
+ data_name: &str,
+ file: &TeaclaveOutputFile,
+ user_id: &str,
+) -> Result<()> {
+ if file.hash.is_some() {
+ return Err(anyhow!("no permission"));
+ }
+ if !file.owner.contains(&user_id.to_string()) {
+ return Err(anyhow!("no permission"));
+ }
+ match task.output_data_owner_list.get(data_name) {
+ Some(data_owner_list) => {
+ let user_id_list = &data_owner_list.user_id_list;
+ if user_id_list.len() != file.owner.len() {
+ return Err(anyhow!("no permission"));
+ }
+ for owner in user_id_list.iter() {
+ if !file.owner.contains(owner) {
return Err(anyhow!("no permission"));
}
- for owner in user_id_list.iter() {
- if !fusion_data.data_owner_id_list.contains(owner) {
- return Err(anyhow!("no permission"));
- }
- }
}
- None => return Err(anyhow!("no such this input name")),
- }
- self.input_map
- .insert(data_name.to_string(), fusion_data.data_id.to_owned());
- Ok(())
- }
-
- pub(crate) fn is_task_id(id: &str) -> bool {
- id.starts_with(TASK_PREFIX)
- }
-
- pub(crate) fn try_update_to_ready_status(&mut self) {
- match self.status {
- TaskStatus::Created => {}
- _ => return,
- }
-
- // check input
- let input_args: HashSet<String> =
self.input_data_owner_list.keys().cloned().collect();
- let assiged_inputs: HashSet<String> =
self.input_map.keys().cloned().collect();
- let diff: HashSet<_> =
input_args.difference(&assiged_inputs).collect();
- if !diff.is_empty() {
- return;
- }
-
- // check output
- let output_args: HashSet<String> =
self.output_data_owner_list.keys().cloned().collect();
- let assiged_outputs: HashSet<String> =
self.output_map.keys().cloned().collect();
- let diff: HashSet<_> =
output_args.difference(&assiged_outputs).collect();
- if !diff.is_empty() {
- return;
}
- self.status = TaskStatus::Ready;
- }
-
- pub(crate) fn try_update_to_approved_status(&mut self) {
- match self.status {
- TaskStatus::Ready => {}
- _ => return,
- }
- let participants: HashSet<&String> =
self.participants.iter().collect();
- let approved_users: HashSet<&String> =
self.approved_user_list.iter().collect();
-
- let diff: HashSet<_> =
participants.difference(&approved_users).collect();
- if !diff.is_empty() {
- return;
- }
- self.status = TaskStatus::Approved;
- }
+ None => return Err(anyhow!("no such output name")),
+ };
+ task.output_map
+ .insert(data_name.to_owned(), file.external_id());
+ Ok(())
}
-impl StagedTask {
- pub(crate) fn new(
- task_id: &str,
- function: Function,
- arg_list: HashMap<String, String>,
- input_map: HashMap<String, InputData>,
- output_map: HashMap<String, OutputData>,
- ) -> Self {
- Self {
- staged_task_id: format!("{}{}", STAGED_TASK_PREFIX, task_id),
- task_id: task_id.to_owned(),
- function_id: function.function_id,
- function_payload: function.payload,
- arg_list,
- input_map,
- output_map,
- }
+pub(crate) fn try_update_task_to_ready_status(task: &mut Task) {
+ match task.status {
+ TaskStatus::Created => {}
+ _ => return,
}
- pub(crate) fn get_queue_key() -> Vec<u8> {
- QUEUE_KEY.as_bytes().to_vec()
+ // check input
+ let input_args: HashSet<String> =
task.input_data_owner_list.keys().cloned().collect();
+ let assiged_inputs: HashSet<String> =
task.input_map.keys().cloned().collect();
+ let diff: HashSet<_> = input_args.difference(&assiged_inputs).collect();
+ if !diff.is_empty() {
+ return;
}
- #[cfg(any(test_mod, feature = "enclave_unit_test"))]
- pub(crate) fn from_slice(bytes: &[u8]) -> Result<Self> {
- let ret: StagedTask =
- serde_json::from_slice(&bytes).map_err(|_| anyhow!("failed to
Deserialize"))?;
- Ok(ret)
- }
-
- pub(crate) fn to_vec(&self) -> Result<Vec<u8>> {
- serde_json::to_vec(&self).map_err(|_| anyhow!("failed to Serialize"))
+ // check output
+ let output_args: HashSet<String> =
task.output_data_owner_list.keys().cloned().collect();
+ let assiged_outputs: HashSet<String> =
task.output_map.keys().cloned().collect();
+ let diff: HashSet<_> = output_args.difference(&assiged_outputs).collect();
+ if !diff.is_empty() {
+ return;
}
+ task.status = TaskStatus::Ready;
}
-impl InputData {
- pub(crate) fn from_input_file(input: TeaclaveInputFile) ->
Result<InputData> {
- Ok(InputData {
- url: input.url,
- hash: input.hash,
- crypto_info: input.crypto_info,
- })
- }
-
- pub(crate) fn from_fusion_data(input: FusionData) -> Result<InputData> {
- let hash = input.hash.ok_or_else(|| anyhow!("invalid fusion data"))?;
- Ok(InputData {
- url: input.url,
- hash,
- crypto_info: input.crypto_info,
- })
+pub(crate) fn try_update_task_to_approved_status(task: &mut Task) {
+ match task.status {
+ TaskStatus::Ready => {}
+ _ => return,
}
-}
+ let participants: HashSet<&String> = task.participants.iter().collect();
+ let approved_users: HashSet<&String> =
task.approved_user_list.iter().collect();
-impl OutputData {
- pub(crate) fn from_output_file(output: TeaclaveOutputFile) ->
Result<OutputData> {
- if output.hash.is_some() {
- return Err(anyhow!("invalid output file"));
- }
- Ok(OutputData {
- url: output.url,
- crypto_info: output.crypto_info,
- })
- }
- pub(crate) fn from_fusion_data(output: FusionData) -> Result<OutputData> {
- if output.hash.is_some() {
- return Err(anyhow!("invalid fusion data"));
- }
- Ok(OutputData {
- url: output.url,
- crypto_info: output.crypto_info,
- })
+ let diff: HashSet<_> = participants.difference(&approved_users).collect();
+ if !diff.is_empty() {
+ return;
}
+ task.status = TaskStatus::Approved;
}
diff --git a/services/proto/src/proto/teaclave_common.proto
b/services/proto/src/proto/teaclave_common.proto
index 9f3e2e8..6522d00 100644
--- a/services/proto/src/proto/teaclave_common.proto
+++ b/services/proto/src/proto/teaclave_common.proto
@@ -11,3 +11,12 @@ message FileCryptoInfo {
bytes key = 2;
bytes iv = 3;
}
+
+enum TaskStatus {
+ Created = 0;
+ Ready = 1;
+ Approved = 2;
+ Running = 3;
+ Failed = 4;
+ Finished = 5;
+}
diff --git a/services/proto/src/proto/teaclave_frontend_service.proto
b/services/proto/src/proto/teaclave_frontend_service.proto
index c24eba2..b2434f4 100644
--- a/services/proto/src/proto/teaclave_frontend_service.proto
+++ b/services/proto/src/proto/teaclave_frontend_service.proto
@@ -23,21 +23,38 @@ message RegisterOutputFileResponse {
string data_id = 1;
}
+message RegisterFusionOutputRequest {
+ repeated string owner_list = 1;
+}
+
+message RegisterFusionOutputResponse {
+ string data_id = 1;
+}
+
+message RegisterInputFromOutputRequest {
+ string data_id = 1;
+}
+
+message RegisterInputFromOutputResponse {
+ string data_id = 1;
+}
+
message GetOutputFileRequest {
string data_id = 1;
}
message GetOutputFileResponse {
- string hash = 1;
+ repeated string owner = 1;
+ string hash = 2;
}
-message GetFusionDataRequest {
+message GetInputFileRequest {
string data_id = 1;
}
-message GetFusionDataResponse {
- string hash = 1;
- repeated string data_owner_id_list = 2;
+message GetInputFileResponse {
+ repeated string owner = 1;
+ string hash = 2;
}
message FunctionInput {
@@ -50,6 +67,11 @@ message FunctionOutput {
string description = 2;
}
+message DataOwnerList {
+ string data_name = 1;
+ repeated string user_id_list = 2;
+}
+
message RegisterFunctionRequest {
string name = 1;
string description = 2;
@@ -79,11 +101,6 @@ message GetFunctionResponse {
repeated FunctionOutput output_list = 8;
}
-message DataOwnerList {
- string data_name = 1;
- repeated string user_id_list = 2;
-}
-
message DataMap {
string data_name = 1;
string data_id = 2;
@@ -109,15 +126,6 @@ message GetTaskRequest {
string task_id = 1;
}
-enum TaskStatus {
- Created = 0;
- Ready = 1;
- Approved = 2;
- Running = 3;
- Failed = 4;
- Finished = 5;
-}
-
message GetTaskResponse {
string task_id = 1;
string creator = 2;
@@ -130,7 +138,7 @@ message GetTaskResponse {
repeated string approved_user_list = 9;
repeated DataMap input_map = 10;
repeated DataMap output_map = 11;
- TaskStatus status = 12;
+ teaclave_common_proto.TaskStatus status = 12;
}
message AssignDataRequest {
@@ -156,8 +164,10 @@ message InvokeTaskResponse { }
service TeaclaveFrontend {
rpc RegisterInputFile (RegisterInputFileRequest) returns
(RegisterInputFileResponse);
rpc RegisterOutputFile (RegisterOutputFileRequest) returns
(RegisterOutputFileResponse);
+ rpc RegisterFusionOutput (RegisterFusionOutputRequest) returns
(RegisterFusionOutputResponse);
+ rpc RegisterInputFromOutput (RegisterInputFromOutputRequest) returns
(RegisterInputFromOutputResponse);
rpc GetOutputFile (GetOutputFileRequest) returns (GetOutputFileResponse);
- rpc GetFusionData (GetFusionDataRequest) returns (GetFusionDataResponse);
+ rpc GetInputFile (GetInputFileRequest) returns (GetInputFileResponse);
rpc RegisterFunction (RegisterFunctionRequest) returns
(RegisterFunctionResponse);
rpc GetFunction (GetFunctionRequest) returns (GetFunctionResponse);
rpc CreateTask (CreateTaskRequest) returns (CreateTaskResponse);
diff --git a/services/proto/src/proto/teaclave_management_service.proto
b/services/proto/src/proto/teaclave_management_service.proto
index 443f6f6..b026b6f 100644
--- a/services/proto/src/proto/teaclave_management_service.proto
+++ b/services/proto/src/proto/teaclave_management_service.proto
@@ -7,8 +7,10 @@ import "teaclave_frontend_service.proto";
service TeaclaveManagement {
rpc RegisterInputFile
(teaclave_frontend_service_proto.RegisterInputFileRequest) returns
(teaclave_frontend_service_proto.RegisterInputFileResponse);
rpc RegisterOutputFile
(teaclave_frontend_service_proto.RegisterOutputFileRequest) returns
(teaclave_frontend_service_proto.RegisterOutputFileResponse);
+ rpc RegisterFusionOutput
(teaclave_frontend_service_proto.RegisterFusionOutputRequest) returns
(teaclave_frontend_service_proto.RegisterFusionOutputResponse);
+ rpc RegisterInputFromOutput
(teaclave_frontend_service_proto.RegisterInputFromOutputRequest) returns
(teaclave_frontend_service_proto.RegisterInputFromOutputResponse);
rpc GetOutputFile (teaclave_frontend_service_proto.GetOutputFileRequest)
returns (teaclave_frontend_service_proto.GetOutputFileResponse);
- rpc GetFusionData (teaclave_frontend_service_proto.GetFusionDataRequest)
returns (teaclave_frontend_service_proto.GetFusionDataResponse);
+ rpc GetInputFile (teaclave_frontend_service_proto.GetInputFileRequest)
returns (teaclave_frontend_service_proto.GetInputFileResponse);
rpc RegisterFunction
(teaclave_frontend_service_proto.RegisterFunctionRequest) returns
(teaclave_frontend_service_proto.RegisterFunctionResponse);
rpc GetFunction (teaclave_frontend_service_proto.GetFunctionRequest) returns
(teaclave_frontend_service_proto.GetFunctionResponse);
rpc CreateTask (teaclave_frontend_service_proto.CreateTaskRequest) returns
(teaclave_frontend_service_proto.CreateTaskResponse);
diff --git a/services/proto/src/teaclave_common.rs
b/services/proto/src/teaclave_common.rs
index 354f46a..4126579 100644
--- a/services/proto/src/teaclave_common.rs
+++ b/services/proto/src/teaclave_common.rs
@@ -2,9 +2,8 @@
use std::prelude::v1::*;
use crate::teaclave_common_proto as proto;
-use anyhow::{Error, Result};
-use teaclave_types::TeaclaveFileCryptoInfo;
-use teaclave_types::TeaclaveFileRootKey128;
+use anyhow::{anyhow, Error, Result};
+use teaclave_types::{TaskStatus, TeaclaveFileCryptoInfo,
TeaclaveFileRootKey128};
#[derive(Debug)]
pub struct UserCredential {
@@ -84,3 +83,27 @@ impl std::convert::From<TeaclaveFileRootKey128> for
proto::FileCryptoInfo {
}
}
}
+
+pub fn i32_to_task_status(status: i32) -> Result<TaskStatus> {
+ let ret = match proto::TaskStatus::from_i32(status) {
+ Some(proto::TaskStatus::Created) => TaskStatus::Created,
+ Some(proto::TaskStatus::Ready) => TaskStatus::Ready,
+ Some(proto::TaskStatus::Approved) => TaskStatus::Approved,
+ Some(proto::TaskStatus::Running) => TaskStatus::Running,
+ Some(proto::TaskStatus::Failed) => TaskStatus::Failed,
+ Some(proto::TaskStatus::Finished) => TaskStatus::Finished,
+ None => return Err(anyhow!("invalid task status")),
+ };
+ Ok(ret)
+}
+
+pub fn i32_from_task_status(status: TaskStatus) -> i32 {
+ match status {
+ TaskStatus::Created => proto::TaskStatus::Created as i32,
+ TaskStatus::Ready => proto::TaskStatus::Ready as i32,
+ TaskStatus::Approved => proto::TaskStatus::Approved as i32,
+ TaskStatus::Running => proto::TaskStatus::Running as i32,
+ TaskStatus::Failed => proto::TaskStatus::Failed as i32,
+ TaskStatus::Finished => proto::TaskStatus::Finished as i32,
+ }
+}
diff --git a/services/proto/src/teaclave_frontend_service.rs
b/services/proto/src/teaclave_frontend_service.rs
index de28fd4..e76b1ef 100644
--- a/services/proto/src/teaclave_frontend_service.rs
+++ b/services/proto/src/teaclave_frontend_service.rs
@@ -1,3 +1,4 @@
+use crate::teaclave_common::{i32_from_task_status, i32_to_task_status};
use crate::teaclave_frontend_service_proto as proto;
use crate::teaclave_management_service::TeaclaveManagementRequest;
use crate::teaclave_management_service::TeaclaveManagementResponse;
@@ -5,11 +6,12 @@ use anyhow::anyhow;
use anyhow::{Error, Result};
use core::convert::TryInto;
use core::iter::FromIterator;
-use serde::{Deserialize, Serialize};
use std::collections::{HashMap, HashSet};
use std::prelude::v1::*;
use teaclave_rpc::into_request;
-use teaclave_types::TeaclaveFileCryptoInfo;
+use teaclave_types::{
+ DataOwnerList, FunctionInput, FunctionOutput, TaskStatus,
TeaclaveFileCryptoInfo,
+};
use url::Url;
pub use proto::TeaclaveFrontend;
@@ -48,43 +50,62 @@ pub struct RegisterOutputFileResponse {
pub data_id: String,
}
-#[into_request(TeaclaveManagementRequest::GetOutputFile)]
-#[into_request(TeaclaveFrontendRequest::GetOutputFile)]
+#[into_request(TeaclaveFrontendRequest::RegisterFusionOutput)]
+#[into_request(TeaclaveManagementRequest::RegisterFusionOutput)]
#[derive(Debug)]
-pub struct GetOutputFileRequest {
+pub struct RegisterFusionOutputRequest {
+ pub owner_list: HashSet<String>,
+}
+
+#[into_request(TeaclaveFrontendResponse::RegisterFusionOutput)]
+#[into_request(TeaclaveManagementResponse::RegisterFusionOutput)]
+#[derive(Debug)]
+pub struct RegisterFusionOutputResponse {
pub data_id: String,
}
-#[into_request(TeaclaveManagementResponse::GetOutputFile)]
+#[into_request(TeaclaveFrontendRequest::RegisterInputFromOutput)]
+#[into_request(TeaclaveManagementRequest::RegisterInputFromOutput)]
#[derive(Debug)]
-pub struct GetOutputFileResponse {
- pub hash: String,
+pub struct RegisterInputFromOutputRequest {
+ pub data_id: String,
}
-#[into_request(TeaclaveManagementRequest::GetFusionData)]
-#[into_request(TeaclaveFrontendRequest::GetFusionData)]
+#[into_request(TeaclaveFrontendResponse::RegisterInputFromOutput)]
+#[into_request(TeaclaveManagementResponse::RegisterInputFromOutput)]
#[derive(Debug)]
-pub struct GetFusionDataRequest {
+pub struct RegisterInputFromOutputResponse {
pub data_id: String,
}
-#[into_request(TeaclaveManagementResponse::GetFusionData)]
+#[into_request(TeaclaveFrontendRequest::GetInputFile)]
+#[into_request(TeaclaveManagementRequest::GetInputFile)]
#[derive(Debug)]
-pub struct GetFusionDataResponse {
+pub struct GetInputFileRequest {
+ pub data_id: String,
+}
+
+#[into_request(TeaclaveFrontendResponse::GetInputFile)]
+#[into_request(TeaclaveManagementResponse::GetInputFile)]
+#[derive(Debug)]
+pub struct GetInputFileResponse {
+ pub owner: HashSet<String>,
pub hash: String,
- pub data_owner_id_list: Vec<String>,
}
-#[derive(Debug, Deserialize, Serialize)]
-pub struct FunctionInput {
- pub name: String,
- pub description: String,
+#[into_request(TeaclaveFrontendRequest::GetOutputFile)]
+#[into_request(TeaclaveManagementRequest::GetOutputFile)]
+#[derive(Debug)]
+pub struct GetOutputFileRequest {
+ pub data_id: String,
}
-#[derive(Debug, Deserialize, Serialize)]
-pub struct FunctionOutput {
- pub name: String,
- pub description: String,
+#[into_request(TeaclaveFrontendResponse::GetOutputFile)]
+#[into_request(TeaclaveManagementResponse::GetOutputFile)]
+#[derive(Debug)]
+pub struct GetOutputFileResponse {
+ pub owner: HashSet<String>,
+ pub hash: String,
}
#[into_request(TeaclaveManagementRequest::RegisterFunction)]
@@ -126,11 +147,6 @@ pub struct GetFunctionResponse {
pub output_list: Vec<FunctionOutput>,
}
-#[derive(Debug, Deserialize, Serialize, Clone)]
-pub struct DataOwnerList {
- pub user_id_list: HashSet<String>,
-}
-
#[into_request(TeaclaveManagementRequest::CreateTask)]
#[into_request(TeaclaveFrontendRequest::CreateTask)]
#[derive(Debug)]
@@ -147,22 +163,6 @@ pub struct CreateTaskResponse {
pub task_id: String,
}
-#[derive(Debug)]
-pub struct DataMap {
- pub data_name: String,
- pub data_id: String,
-}
-
-#[derive(Debug, Deserialize, Serialize, std::cmp::PartialEq)]
-pub enum TaskStatus {
- Created,
- Ready,
- Approved,
- Running,
- Failed,
- Finished,
-}
-
#[into_request(TeaclaveManagementRequest::GetTask)]
#[into_request(TeaclaveFrontendRequest::GetTask)]
#[derive(Debug)]
@@ -219,67 +219,6 @@ pub struct InvokeTaskRequest {
#[derive(Debug)]
pub struct InvokeTaskResponse;
-fn arg_list_from_proto(vector: Vec<proto::Argument>) -> Result<HashMap<String,
String>> {
- let mut ret = HashMap::with_capacity(vector.len());
- for item in vector.into_iter() {
- ret.insert(item.arg_name, item.arg_value);
- }
- Ok(ret)
-}
-
-fn arg_list_to_proto(map: HashMap<String, String>) -> Vec<proto::Argument> {
- let mut ret = Vec::with_capacity(map.len());
- for (arg_name, arg_value) in map.into_iter() {
- let argument = proto::Argument {
- arg_name,
- arg_value,
- };
- ret.push(argument);
- }
- ret
-}
-
-fn data_map_to_proto(map: HashMap<String, String>) -> Vec<proto::DataMap> {
- let mut ret = Vec::with_capacity(map.len());
- for (data_name, data_id) in map.into_iter() {
- let data_map = proto::DataMap { data_name, data_id };
- ret.push(data_map);
- }
- ret
-}
-
-fn data_map_from_proto(vector: Vec<proto::DataMap>) -> Result<HashMap<String,
String>> {
- let mut ret = HashMap::with_capacity(vector.len());
- for item in vector.into_iter() {
- ret.insert(item.data_name, item.data_id);
- }
- Ok(ret)
-}
-
-fn data_owner_list_from_proto(
- vector: Vec<proto::DataOwnerList>,
-) -> Result<HashMap<String, DataOwnerList>> {
- let mut ret = HashMap::with_capacity(vector.len());
- for item in vector.into_iter() {
- let data_owner_list = DataOwnerList {
- user_id_list: HashSet::from_iter(item.user_id_list.into_iter()),
- };
- ret.insert(item.data_name, data_owner_list);
- }
- Ok(ret)
-}
-
-fn data_owner_list_to_proto(map: HashMap<String, DataOwnerList>) ->
Vec<proto::DataOwnerList> {
- let mut ret = Vec::with_capacity(map.len());
- for (data_name, data_owner_list) in map.into_iter() {
- let data_owner_list = proto::DataOwnerList {
- data_name,
- user_id_list: data_owner_list.user_id_list.into_iter().collect(),
- };
- ret.push(data_owner_list);
- }
- ret
-}
impl std::convert::TryFrom<proto::RegisterInputFileRequest> for
RegisterInputFileRequest {
type Error = Error;
@@ -368,10 +307,50 @@ impl From<RegisterOutputFileResponse> for
proto::RegisterOutputFileResponse {
}
}
-impl std::convert::TryFrom<proto::GetOutputFileRequest> for
GetOutputFileRequest {
+impl std::convert::TryFrom<proto::RegisterFusionOutputRequest> for
RegisterFusionOutputRequest {
type Error = Error;
- fn try_from(proto: proto::GetOutputFileRequest) -> Result<Self> {
+ fn try_from(proto: proto::RegisterFusionOutputRequest) -> Result<Self> {
+ let ret = Self {
+ owner_list: proto.owner_list.into_iter().collect(),
+ };
+
+ Ok(ret)
+ }
+}
+
+impl From<RegisterFusionOutputRequest> for proto::RegisterFusionOutputRequest {
+ fn from(request: RegisterFusionOutputRequest) -> Self {
+ Self {
+ owner_list: request.owner_list.into_iter().collect(),
+ }
+ }
+}
+
+impl std::convert::TryFrom<proto::RegisterFusionOutputResponse> for
RegisterFusionOutputResponse {
+ type Error = Error;
+
+ fn try_from(proto: proto::RegisterFusionOutputResponse) -> Result<Self> {
+ Ok(Self {
+ data_id: proto.data_id,
+ })
+ }
+}
+
+impl From<RegisterFusionOutputResponse> for
proto::RegisterFusionOutputResponse {
+ fn from(request: RegisterFusionOutputResponse) -> Self {
+ Self {
+ data_id: request.data_id,
+ }
+ }
+}
+
+impl std::convert::TryFrom<proto::RegisterInputFromOutputRequest>
+ for RegisterInputFromOutputRequest
+{
+ type Error = Error;
+
+ fn try_from(proto: proto::RegisterInputFromOutputRequest) -> Result<Self> {
let ret = Self {
data_id: proto.data_id,
};
@@ -380,34 +359,78 @@ impl std::convert::TryFrom<proto::GetOutputFileRequest>
for GetOutputFileRequest
}
}
-impl From<GetOutputFileRequest> for proto::GetOutputFileRequest {
- fn from(request: GetOutputFileRequest) -> Self {
+impl From<RegisterInputFromOutputRequest> for
proto::RegisterInputFromOutputRequest {
+ fn from(request: RegisterInputFromOutputRequest) -> Self {
Self {
data_id: request.data_id,
}
}
}
-impl std::convert::TryFrom<proto::GetOutputFileResponse> for
GetOutputFileResponse {
+impl std::convert::TryFrom<proto::RegisterInputFromOutputResponse>
+ for RegisterInputFromOutputResponse
+{
type Error = Error;
- fn try_from(proto: proto::GetOutputFileResponse) -> Result<Self> {
- Ok(Self { hash: proto.hash })
+ fn try_from(proto: proto::RegisterInputFromOutputResponse) -> Result<Self>
{
+ Ok(Self {
+ data_id: proto.data_id,
+ })
}
}
-impl From<GetOutputFileResponse> for proto::GetOutputFileResponse {
- fn from(response: GetOutputFileResponse) -> Self {
+impl From<RegisterInputFromOutputResponse> for
proto::RegisterInputFromOutputResponse {
+ fn from(request: RegisterInputFromOutputResponse) -> Self {
+ Self {
+ data_id: request.data_id,
+ }
+ }
+}
+
+impl std::convert::TryFrom<proto::GetInputFileRequest> for GetInputFileRequest
{
+ type Error = Error;
+
+ fn try_from(proto: proto::GetInputFileRequest) -> Result<Self> {
+ let ret = Self {
+ data_id: proto.data_id,
+ };
+
+ Ok(ret)
+ }
+}
+
+impl From<GetInputFileRequest> for proto::GetInputFileRequest {
+ fn from(request: GetInputFileRequest) -> Self {
Self {
- hash: response.hash,
+ data_id: request.data_id,
}
}
}
-impl std::convert::TryFrom<proto::GetFusionDataRequest> for
GetFusionDataRequest {
+impl std::convert::TryFrom<proto::GetInputFileResponse> for
GetInputFileResponse {
type Error = Error;
- fn try_from(proto: proto::GetFusionDataRequest) -> Result<Self> {
+ fn try_from(proto: proto::GetInputFileResponse) -> Result<Self> {
+ Ok(Self {
+ owner: proto.owner.into_iter().collect(),
+ hash: proto.hash,
+ })
+ }
+}
+
+impl From<GetInputFileResponse> for proto::GetInputFileResponse {
+ fn from(request: GetInputFileResponse) -> Self {
+ Self {
+ owner: request.owner.into_iter().collect(),
+ hash: request.hash,
+ }
+ }
+}
+
+impl std::convert::TryFrom<proto::GetOutputFileRequest> for
GetOutputFileRequest {
+ type Error = Error;
+
+ fn try_from(proto: proto::GetOutputFileRequest) -> Result<Self> {
let ret = Self {
data_id: proto.data_id,
};
@@ -416,30 +439,30 @@ impl std::convert::TryFrom<proto::GetFusionDataRequest>
for GetFusionDataRequest
}
}
-impl From<GetFusionDataRequest> for proto::GetFusionDataRequest {
- fn from(request: GetFusionDataRequest) -> Self {
+impl From<GetOutputFileRequest> for proto::GetOutputFileRequest {
+ fn from(request: GetOutputFileRequest) -> Self {
Self {
data_id: request.data_id,
}
}
}
-impl std::convert::TryFrom<proto::GetFusionDataResponse> for
GetFusionDataResponse {
+impl std::convert::TryFrom<proto::GetOutputFileResponse> for
GetOutputFileResponse {
type Error = Error;
- fn try_from(proto: proto::GetFusionDataResponse) -> Result<Self> {
+ fn try_from(proto: proto::GetOutputFileResponse) -> Result<Self> {
Ok(Self {
+ owner: proto.owner.into_iter().collect(),
hash: proto.hash,
- data_owner_id_list: proto.data_owner_id_list,
})
}
}
-impl From<GetFusionDataResponse> for proto::GetFusionDataResponse {
- fn from(response: GetFusionDataResponse) -> Self {
+impl From<GetOutputFileResponse> for proto::GetOutputFileResponse {
+ fn from(request: GetOutputFileResponse) -> Self {
Self {
- hash: response.hash,
- data_owner_id_list: response.data_owner_id_list,
+ owner: request.owner.into_iter().collect(),
+ hash: request.hash,
}
}
}
@@ -637,6 +660,53 @@ impl From<GetFunctionResponse> for
proto::GetFunctionResponse {
}
}
+pub fn data_owner_list_from_proto(
+ vector: Vec<proto::DataOwnerList>,
+) -> Result<HashMap<String, DataOwnerList>> {
+ let mut ret = HashMap::with_capacity(vector.len());
+ for item in vector.into_iter() {
+ let data_owner_list = DataOwnerList {
+ user_id_list: HashSet::from_iter(item.user_id_list.into_iter()),
+ };
+ ret.insert(item.data_name, data_owner_list);
+ }
+ Ok(ret)
+}
+
+pub fn data_owner_list_to_proto<S: std::hash::BuildHasher>(
+ map: HashMap<String, DataOwnerList, S>,
+) -> Vec<proto::DataOwnerList> {
+ let mut ret = Vec::with_capacity(map.len());
+ for (data_name, data_owner_list) in map.into_iter() {
+ let data_owner_list = proto::DataOwnerList {
+ data_name,
+ user_id_list: data_owner_list.user_id_list.into_iter().collect(),
+ };
+ ret.push(data_owner_list);
+ }
+ ret
+}
+
+fn arg_list_from_proto(vector: Vec<proto::Argument>) -> Result<HashMap<String,
String>> {
+ let mut ret = HashMap::with_capacity(vector.len());
+ for item in vector.into_iter() {
+ ret.insert(item.arg_name, item.arg_value);
+ }
+ Ok(ret)
+}
+
+fn arg_list_to_proto(map: HashMap<String, String>) -> Vec<proto::Argument> {
+ let mut ret = Vec::with_capacity(map.len());
+ for (arg_name, arg_value) in map.into_iter() {
+ let argument = proto::Argument {
+ arg_name,
+ arg_value,
+ };
+ ret.push(argument);
+ }
+ ret
+}
+
impl std::convert::TryFrom<proto::CreateTaskRequest> for CreateTaskRequest {
type Error = Error;
@@ -689,34 +759,21 @@ impl From<CreateTaskResponse> for
proto::CreateTaskResponse {
}
}
-impl std::convert::TryFrom<i32> for TaskStatus {
- type Error = Error;
-
- fn try_from(status: i32) -> Result<Self> {
- let ret = match proto::TaskStatus::from_i32(status) {
- Some(proto::TaskStatus::Created) => TaskStatus::Created,
- Some(proto::TaskStatus::Ready) => TaskStatus::Ready,
- Some(proto::TaskStatus::Approved) => TaskStatus::Approved,
- Some(proto::TaskStatus::Running) => TaskStatus::Running,
- Some(proto::TaskStatus::Failed) => TaskStatus::Failed,
- Some(proto::TaskStatus::Finished) => TaskStatus::Finished,
- None => return Err(anyhow!("invalid task status")),
- };
- Ok(ret)
+fn data_map_to_proto(map: HashMap<String, String>) -> Vec<proto::DataMap> {
+ let mut ret = Vec::with_capacity(map.len());
+ for (data_name, data_id) in map.into_iter() {
+ let data_map = proto::DataMap { data_name, data_id };
+ ret.push(data_map);
}
+ ret
}
-impl From<TaskStatus> for i32 {
- fn from(status: TaskStatus) -> i32 {
- match status {
- TaskStatus::Created => proto::TaskStatus::Created as i32,
- TaskStatus::Ready => proto::TaskStatus::Ready as i32,
- TaskStatus::Approved => proto::TaskStatus::Approved as i32,
- TaskStatus::Running => proto::TaskStatus::Running as i32,
- TaskStatus::Failed => proto::TaskStatus::Failed as i32,
- TaskStatus::Finished => proto::TaskStatus::Finished as i32,
- }
+fn data_map_from_proto(vector: Vec<proto::DataMap>) -> Result<HashMap<String,
String>> {
+ let mut ret = HashMap::with_capacity(vector.len());
+ for item in vector.into_iter() {
+ ret.insert(item.data_name, item.data_id);
}
+ Ok(ret)
}
impl std::convert::TryFrom<proto::GetTaskRequest> for GetTaskRequest {
@@ -748,7 +805,7 @@ impl std::convert::TryFrom<proto::GetTaskResponse> for
GetTaskResponse {
let output_data_owner_list =
data_owner_list_from_proto(proto.output_data_owner_list)?;
let input_map = data_map_from_proto(proto.input_map)?;
let output_map = data_map_from_proto(proto.output_map)?;
- let status = TaskStatus::try_from(proto.status)?;
+ let status = i32_to_task_status(proto.status)?;
let ret = Self {
task_id: proto.task_id,
@@ -776,7 +833,7 @@ impl From<GetTaskResponse> for proto::GetTaskResponse {
let output_data_owner_list =
data_owner_list_to_proto(response.output_data_owner_list);
let input_map = data_map_to_proto(response.input_map);
let output_map = data_map_to_proto(response.output_map);
- let status = i32::from(response.status);
+ let status = i32_from_task_status(response.status);
Self {
task_id: response.task_id,
creator: response.creator,
diff --git a/services/proto/src/teaclave_management_service.rs
b/services/proto/src/teaclave_management_service.rs
index 9b5013b..55edd23 100644
--- a/services/proto/src/teaclave_management_service.rs
+++ b/services/proto/src/teaclave_management_service.rs
@@ -9,10 +9,18 @@ pub type RegisterInputFileRequest =
crate::teaclave_frontend_service::RegisterIn
pub type RegisterInputFileResponse =
crate::teaclave_frontend_service::RegisterInputFileResponse;
pub type RegisterOutputFileRequest =
crate::teaclave_frontend_service::RegisterOutputFileRequest;
pub type RegisterOutputFileResponse =
crate::teaclave_frontend_service::RegisterOutputFileResponse;
+pub type RegisterFusionOutputRequest =
+ crate::teaclave_frontend_service::RegisterFusionOutputRequest;
+pub type RegisterFusionOutputResponse =
+ crate::teaclave_frontend_service::RegisterFusionOutputResponse;
+pub type RegisterInputFromOutputRequest =
+ crate::teaclave_frontend_service::RegisterInputFromOutputRequest;
+pub type RegisterInputFromOutputResponse =
+ crate::teaclave_frontend_service::RegisterInputFromOutputResponse;
+pub type GetInputFileRequest =
crate::teaclave_frontend_service::GetInputFileRequest;
+pub type GetInputFileResponse =
crate::teaclave_frontend_service::GetInputFileResponse;
pub type GetOutputFileRequest =
crate::teaclave_frontend_service::GetOutputFileRequest;
pub type GetOutputFileResponse =
crate::teaclave_frontend_service::GetOutputFileResponse;
-pub type GetFusionDataRequest =
crate::teaclave_frontend_service::GetFusionDataRequest;
-pub type GetFusionDataResponse =
crate::teaclave_frontend_service::GetFusionDataResponse;
pub type RegisterFunctionRequest =
crate::teaclave_frontend_service::RegisterFunctionRequest;
pub type RegisterFunctionResponse =
crate::teaclave_frontend_service::RegisterFunctionResponse;
pub type GetFunctionRequest =
crate::teaclave_frontend_service::GetFunctionRequest;
diff --git a/tests/functional/enclave/src/teaclave_frontend_service.rs
b/tests/functional/enclave/src/teaclave_frontend_service.rs
index ca2e2a3..a67e75d 100644
--- a/tests/functional/enclave/src/teaclave_frontend_service.rs
+++ b/tests/functional/enclave/src/teaclave_frontend_service.rs
@@ -17,8 +17,10 @@ pub fn run_tests() -> bool {
run_tests!(
test_register_input_file,
test_register_output_file,
+ test_register_fusion_output,
+ test_register_input_from_output,
test_get_output_file,
- test_get_fusion_data,
+ test_get_input_file,
test_register_function,
test_get_function,
test_create_task,
@@ -123,6 +125,51 @@ fn test_register_output_file() {
assert!(response.is_err());
}
+fn test_register_fusion_output() {
+ let mut client = get_client();
+ let request = RegisterFusionOutputRequest {
+ owner_list: vec!["frontend_user", "mock_user"]
+ .into_iter()
+ .map(|s| s.to_string())
+ .collect(),
+ };
+ let response = client.register_fusion_output(request);
+ assert!(response.is_ok());
+ assert!(!response.unwrap().data_id.is_empty());
+
+ let request = RegisterFusionOutputRequest {
+ owner_list: vec!["frontend_user", "mock_user"]
+ .into_iter()
+ .map(|s| s.to_string())
+ .collect(),
+ };
+ client
+ .metadata_mut()
+ .insert("token".to_string(), "wrong token".to_string());
+ let response = client.register_fusion_output(request);
+ assert!(response.is_err());
+}
+
+fn test_register_input_from_output() {
+ let mut client = get_client();
+ let data_id = "output-file-00000000-0000-0000-0000-000000000001";
+ let request = RegisterInputFromOutputRequest {
+ data_id: data_id.to_string(),
+ };
+ let response = client.register_input_from_output(request);
+ assert!(response.is_ok());
+ assert!(!response.unwrap().data_id.is_empty());
+
+ let request = RegisterInputFromOutputRequest {
+ data_id: data_id.to_string(),
+ };
+ client
+ .metadata_mut()
+ .insert("token".to_string(), "wrong token".to_string());
+ let response = client.register_input_from_output(request);
+ assert!(response.is_err());
+}
+
fn test_get_output_file() {
let request = RegisterOutputFileRequest {
url:
Url::parse("s3://s3.us-west-2.amazonaws.com/mybucket/puppy.jpg.enc?key-id=deadbeefdeadbeef&key=deadbeefdeadbeef").unwrap(),
@@ -148,23 +195,29 @@ fn test_get_output_file() {
assert!(response.is_err());
}
-fn test_get_fusion_data() {
+fn test_get_input_file() {
+ let request = RegisterInputFileRequest {
+ url:
Url::parse("s3://s3.us-west-2.amazonaws.com/mybucket/puppy.jpg.enc?key-id=deadbeefdeadbeef&key=deadbeefdeadbeef").unwrap(),
+ hash: "deadbeef".to_string(),
+ crypto_info: TeaclaveFileCryptoInfo::default(),
+ };
+
let mut client = get_client();
+ let response = client.register_input_file(request);
+ let data_id = response.unwrap().data_id;
- let request = GetFusionDataRequest {
- data_id: "fusion-data-mock-frontend-data".to_string(),
+ let request = GetInputFileRequest {
+ data_id: data_id.clone(),
};
- let response = client.get_fusion_data(request);
+ let response = client.get_input_file(request);
assert!(response.is_ok());
- assert!(response.unwrap().hash.is_empty());
+ assert!(!response.unwrap().hash.is_empty());
- let request = GetFusionDataRequest {
- data_id: "fusion-data-mock-frontend-data".to_string(),
- };
+ let request = GetInputFileRequest { data_id };
client
.metadata_mut()
.insert("token".to_string(), "wrong token".to_string());
- let response = client.get_fusion_data(request);
+ let response = client.get_input_file(request);
assert!(response.is_err());
}
@@ -204,14 +257,14 @@ fn test_get_function() {
let mut client = get_client();
let request = GetFunctionRequest {
- function_id: "native-mock-simple-func".to_string(),
+ function_id:
"function-00000000-0000-0000-0000-000000000001".to_string(),
};
let response = client.get_function(request);
assert!(response.is_ok());
assert!(!response.unwrap().name.is_empty());
let request = GetFunctionRequest {
- function_id: "native-mock-simple-func".to_string(),
+ function_id:
"function-00000000-0000-0000-0000-000000000001".to_string(),
};
client
.metadata_mut()
@@ -228,10 +281,11 @@ fn test_create_task() {
.into_iter()
.collect(),
};
+ let function_id = "function-00000000-0000-0000-0000-000000000002";
let mut output_data_owner_list = HashMap::new();
output_data_owner_list.insert("output".to_string(), data_owner_id_list);
let request = CreateTaskRequest {
- function_id: "native-mock-simple-func".to_string(),
+ function_id: function_id.to_string(),
arg_list: vec![("arg1".to_string(), "data1".to_string())]
.into_iter()
.collect(),
@@ -243,7 +297,7 @@ fn test_create_task() {
assert!(!response.unwrap().task_id.is_empty());
let request = CreateTaskRequest {
- function_id: "native-mock-simple-func".to_string(),
+ function_id: function_id.to_string(),
arg_list: vec![("arg1".to_string(), "data1".to_string())]
.into_iter()
.collect(),
@@ -268,7 +322,7 @@ fn test_get_task() {
let mut output_data_owner_list = HashMap::new();
output_data_owner_list.insert("output".to_string(), data_owner_id_list);
let request = CreateTaskRequest {
- function_id: "native-mock-simple-func".to_string(),
+ function_id:
"function-00000000-0000-0000-0000-000000000002".to_string(),
arg_list: vec![("arg1".to_string(), "data1".to_string())]
.into_iter()
.collect(),
@@ -302,7 +356,7 @@ fn test_assign_data() {
let mut output_data_owner_list = HashMap::new();
output_data_owner_list.insert("output".to_string(), data_owner_id_list);
let request = CreateTaskRequest {
- function_id: "native-mock-simple-func".to_string(),
+ function_id:
"function-00000000-0000-0000-0000-000000000002".to_string(),
arg_list: vec![("arg1".to_string(), "data1".to_string())]
.into_iter()
.collect(),
@@ -356,7 +410,7 @@ fn test_approve_task() {
let mut output_data_owner_list = HashMap::new();
output_data_owner_list.insert("output".to_string(), data_owner_id_list);
let request = CreateTaskRequest {
- function_id: "native-mock-simple-func".to_string(),
+ function_id:
"function-00000000-0000-0000-0000-000000000002".to_string(),
arg_list: vec![("arg1".to_string(), "data1".to_string())]
.into_iter()
.collect(),
@@ -409,7 +463,7 @@ fn test_invoke_task() {
let mut output_data_owner_list = HashMap::new();
output_data_owner_list.insert("output".to_string(), data_owner_id_list);
let request = CreateTaskRequest {
- function_id: "native-mock-simple-func".to_string(),
+ function_id:
"function-00000000-0000-0000-0000-000000000002".to_string(),
arg_list: vec![("arg1".to_string(), "data1".to_string())]
.into_iter()
.collect(),
diff --git a/tests/functional/enclave/src/teaclave_management_service.rs
b/tests/functional/enclave/src/teaclave_management_service.rs
index 6508b15..625df54 100644
--- a/tests/functional/enclave/src/teaclave_management_service.rs
+++ b/tests/functional/enclave/src/teaclave_management_service.rs
@@ -3,9 +3,9 @@ use std::prelude::v1::*;
use teaclave_attestation::verifier;
use teaclave_config::RuntimeConfig;
use teaclave_config::BUILD_CONFIG;
-use teaclave_proto::teaclave_frontend_service::{
- DataOwnerList, FunctionInput, FunctionOutput, TaskStatus,
-};
+//use teaclave_proto::teaclave_frontend_service::{
+// DataOwnerList, FunctionInput, FunctionOutput, TaskStatus,
+//};
use teaclave_proto::teaclave_management_service::*;
use teaclave_rpc::config::SgxTrustedTlsClientConfig;
use teaclave_rpc::endpoint::Endpoint;
@@ -18,11 +18,13 @@ pub fn run_tests() -> bool {
run_tests!(
test_register_input_file,
test_register_output_file,
- test_register_function,
- test_create_task,
+ test_register_fusion_output,
+ test_register_input_from_output,
+ test_get_input_file,
test_get_output_file,
- test_get_fusion_data,
+ test_register_function,
test_get_function,
+ test_create_task,
test_get_task,
test_assign_data,
test_approve_task,
@@ -91,13 +93,67 @@ fn test_register_output_file() {
assert!(response.is_ok());
}
+fn test_register_fusion_output() {
+ let request = RegisterFusionOutputRequest {
+ owner_list: vec!["mock_user", "mock_user_b"]
+ .into_iter()
+ .map(|s| s.to_string())
+ .collect(),
+ };
+
+ let mut client = get_client("mock_user");
+ let response = client.register_fusion_output(request);
+
+ assert!(response.is_ok());
+
+ let request = RegisterFusionOutputRequest {
+ owner_list: vec!["mock_user_c", "mock_user_b"]
+ .into_iter()
+ .map(|s| s.to_string())
+ .collect(),
+ };
+
+ let mut client = get_client("mock_user");
+ let response = client.register_fusion_output(request);
+ assert!(response.is_err());
+}
+
+fn test_register_input_from_output() {
+ // not a owner
+ let mut client = get_client("mock_user_c");
+ let data_id = "output-file-00000000-0000-0000-0000-000000000001";
+ let request = RegisterInputFromOutputRequest {
+ data_id: data_id.to_string(),
+ };
+ let response = client.register_input_from_output(request);
+ assert!(response.is_err());
+
+ // output not ready
+ let mut client = get_client("mock_user1");
+ let request = RegisterOutputFileRequest {
+ url:
Url::parse("s3://s3.us-west-2.amazonaws.com/mybucket/puppy.jpg.enc?key-id=deadbeefdeadbeef&key=deadbeefdeadbeef").unwrap(),
+ crypto_info: TeaclaveFileCryptoInfo::default(),
+ };
+ let response = client.register_output_file(request);
+ assert!(response.is_ok());
+ let request = RegisterInputFromOutputRequest {
+ data_id: response.unwrap().data_id,
+ };
+ let response = client.register_input_from_output(request);
+ assert!(response.is_err());
+
+ let request = RegisterInputFromOutputRequest {
+ data_id: data_id.to_string(),
+ };
+ let response = client.register_input_from_output(request);
+ assert!(response.is_ok());
+ info!("{:?}", response);
+}
+
fn test_get_output_file() {
let request = RegisterOutputFileRequest {
url:
Url::parse("s3://s3.us-west-2.amazonaws.com/mybucket/puppy.jpg.enc?key-id=deadbeefdeadbeef&key=deadbeefdeadbeef").unwrap(),
- crypto_info: TeaclaveFileCryptoInfo::AesGcm128(AesGcm128CryptoInfo {
- key: [0x90u8; 16],
- iv: [0x89u8; 12],
- }),
+ crypto_info: TeaclaveFileCryptoInfo::default(),
};
let mut client = get_client("mock_user");
@@ -114,32 +170,24 @@ fn test_get_output_file() {
assert!(response.is_err());
}
-fn test_get_fusion_data() {
- let mut client = get_client("mock_user2");
- let request = GetFusionDataRequest {
- data_id: "fusion-data-mock-data".to_string(),
+fn test_get_input_file() {
+ let request = RegisterInputFileRequest {
+ url:
Url::parse("s3://s3.us-west-2.amazonaws.com/mybucket/puppy.jpg.enc?key-id=deadbeefdeadbeef&key=deadbeefdeadbeef").unwrap(),
+ hash: "deadbeef".to_string(),
+ crypto_info: TeaclaveFileCryptoInfo::default(),
};
- let response = client.get_fusion_data(request);
- assert!(response.is_ok());
- let mut client = get_client("mock_user3");
- let request = GetFusionDataRequest {
- data_id: "fusion-data-mock-data".to_string(),
+ let mut client = get_client("mock_user");
+ let response = client.register_input_file(request).unwrap();
+ let data_id = response.data_id;
+ let request = GetInputFileRequest {
+ data_id: data_id.clone(),
};
- let response = client.get_fusion_data(request);
+ let response = client.get_input_file(request);
assert!(response.is_ok());
- let response = response.unwrap();
- assert!(!response.hash.is_empty());
- assert_eq!(
- response.data_owner_id_list,
- ["mock_user2".to_string(), "mock_user3".to_string()]
- );
-
- let mut client = get_client("mock_user_c");
- let request = GetFusionDataRequest {
- data_id: "fusion-data-mock-data".to_string(),
- };
- let response = client.get_fusion_data(request);
+ let mut client = get_client("mock_another_user");
+ let request = GetInputFileRequest { data_id };
+ let response = client.get_input_file(request);
assert!(response.is_err());
}
@@ -202,7 +250,7 @@ fn test_get_function() {
let response = client.get_function(request);
assert!(response.is_err());
let request = GetFunctionRequest {
- function_id: "native-mock-native-func".to_string(),
+ function_id:
"function-00000000-0000-0000-0000-000000000001".to_string(),
};
let response = client.get_function(request);
assert!(response.is_ok());
@@ -229,7 +277,7 @@ fn get_correct_create_task() -> CreateTaskRequest {
output_data_owner_list.insert("output2".to_string(), data_owner_id_list2);
CreateTaskRequest {
- function_id: "native-mock-native-func".to_string(),
+ function_id:
"function-00000000-0000-0000-0000-000000000001".to_string(),
arg_list,
input_data_owner_list,
output_data_owner_list,
@@ -284,7 +332,6 @@ fn test_get_task() {
assert!(response.participants.contains(&name.to_string()));
}
assert!(response.participants.len() == 4);
- assert!(response.output_map.len() == 1);
}
fn test_assign_data() {
@@ -307,7 +354,7 @@ fn test_assign_data() {
let response = unknown_client.assign_data(request);
assert!(response.is_err());
- // user_id != input_file.owner
+ // !input_file.owner.contains(user_id)
let request = RegisterInputFileRequest {
url: Url::parse("input://path").unwrap(),
hash: "deadbeefdeadbeef".to_string(),
@@ -327,7 +374,7 @@ fn test_assign_data() {
let response = client1.assign_data(request);
assert!(response.is_err());
- // user_id != output_file.owner
+ // !output_file.owner.contains(user_id)
let request = RegisterOutputFileRequest {
url: Url::parse("output://path").unwrap(),
crypto_info: TeaclaveFileCryptoInfo::default(),
@@ -372,9 +419,10 @@ fn test_assign_data() {
input_map: HashMap::new(),
output_map: HashMap::new(),
};
- request
- .input_map
- .insert("input".to_string(), "fusion-data-mock-data".to_string());
+ request.input_map.insert(
+ "input".to_string(),
+ "input-file-00000000-0000-0000-0000-000000000002".to_string(),
+ );
let response = client1.assign_data(request);
assert!(response.is_err());
@@ -402,7 +450,7 @@ fn test_assign_data() {
let response = client2.assign_data(request);
assert!(response.is_err());
- //input file: DataOwnerList has one user
+ //input file: DataOwnerList != user_id
let mut request = AssignDataRequest {
task_id: task_id.clone(),
input_map: HashMap::new(),
@@ -426,7 +474,7 @@ fn test_assign_data() {
let response = client2.assign_data(request);
assert!(response.is_err());
- // output file DataOwnerList has one user
+ // output file DataOwnerList != user_id_list
let mut request = AssignDataRequest {
task_id: task_id.clone(),
input_map: HashMap::new(),
@@ -438,7 +486,7 @@ fn test_assign_data() {
let response = client2.assign_data(request);
assert!(response.is_err());
- // output file: DataOwnerList != user_id
+ // output file: DataOwnerList != user_id_list
let mut request = AssignDataRequest {
task_id: task_id.clone(),
input_map: HashMap::new(),
@@ -450,30 +498,6 @@ fn test_assign_data() {
let response = client2.assign_data(request);
assert!(response.is_err());
- // fusion_data in output_map
- let mut request = AssignDataRequest {
- task_id: task_id.clone(),
- input_map: HashMap::new(),
- output_map: HashMap::new(),
- };
- request
- .output_map
- .insert("output2".to_string(), "fusion-data-mock-data".to_string());
- let response = client2.assign_data(request);
- assert!(response.is_err());
-
- // fusion_data: DataOwnerList == fusion_data.owner_id_list
- let mut request = AssignDataRequest {
- task_id: task_id.clone(),
- input_map: HashMap::new(),
- output_map: HashMap::new(),
- };
- request
- .output_map
- .insert("output2".to_string(), "fusion-data-mock-data2".to_string());
- let response = client2.assign_data(request);
- assert!(response.is_err());
-
// assign all the data
let request = RegisterInputFileRequest {
url: Url::parse("input://path").unwrap(),
@@ -509,9 +533,29 @@ fn test_assign_data() {
input_map: HashMap::new(),
output_map: HashMap::new(),
};
+ request.input_map.insert(
+ "input2".to_string(),
+ "input-file-00000000-0000-0000-0000-000000000002".to_string(),
+ );
+ let response = client3.assign_data(request);
+ assert!(response.is_ok());
+
+ let request = RegisterFusionOutputRequest {
+ owner_list: vec!["mock_user2", "mock_user3"]
+ .into_iter()
+ .map(|s| s.to_string())
+ .collect(),
+ };
+ let response = client3.register_fusion_output(request);
+ let fusion_output = response.unwrap().data_id;
+ let mut request = AssignDataRequest {
+ task_id: task_id.clone(),
+ input_map: HashMap::new(),
+ output_map: HashMap::new(),
+ };
request
- .input_map
- .insert("input2".to_string(), "fusion-data-mock-data".to_string());
+ .output_map
+ .insert("output2".to_string(), fusion_output);
let response = client3.assign_data(request);
assert!(response.is_ok());
@@ -519,7 +563,6 @@ fn test_assign_data() {
task_id: task_id.clone(),
};
let response = client3.get_task(request);
- info!("{:?}", response);
assert_eq!(response.unwrap().status, TaskStatus::Ready);
// task.status != Created
@@ -585,12 +628,32 @@ fn test_approve_task() {
input_map: HashMap::new(),
output_map: HashMap::new(),
};
- request
- .input_map
- .insert("input2".to_string(), "fusion-data-mock-data".to_string());
+ request.input_map.insert(
+ "input2".to_string(),
+ "input-file-00000000-0000-0000-0000-000000000002".to_string(),
+ );
let response = client2.assign_data(request);
assert!(response.is_ok());
+ let request = RegisterFusionOutputRequest {
+ owner_list: vec!["mock_user2", "mock_user3"]
+ .into_iter()
+ .map(|s| s.to_string())
+ .collect(),
+ };
+ let response = client3.register_fusion_output(request);
+ let fusion_output = response.unwrap().data_id;
+ let mut request = AssignDataRequest {
+ task_id: task_id.clone(),
+ input_map: HashMap::new(),
+ output_map: HashMap::new(),
+ };
+ request
+ .output_map
+ .insert("output2".to_string(), fusion_output);
+ let response = client3.assign_data(request);
+ assert!(response.is_ok());
+
let request = GetTaskRequest {
task_id: task_id.clone(),
};
@@ -672,10 +735,31 @@ fn test_invoke_task() {
input_map: HashMap::new(),
output_map: HashMap::new(),
};
+ request.input_map.insert(
+ "input2".to_string(),
+ "input-file-00000000-0000-0000-0000-000000000002".to_string(),
+ );
+ let response = client2.assign_data(request);
+ assert!(response.is_ok());
+
+ let request = RegisterFusionOutputRequest {
+ owner_list: vec!["mock_user2", "mock_user3"]
+ .into_iter()
+ .map(|s| s.to_string())
+ .collect(),
+ };
+ let response = client3.register_fusion_output(request);
+ let fusion_output = response.unwrap().data_id;
+ let mut request = AssignDataRequest {
+ task_id: task_id.clone(),
+ input_map: HashMap::new(),
+ output_map: HashMap::new(),
+ };
request
- .input_map
- .insert("input2".to_string(), "fusion-data-mock-data".to_string());
- client2.assign_data(request).unwrap();
+ .output_map
+ .insert("output2".to_string(), fusion_output);
+ let response = client3.assign_data(request);
+ assert!(response.is_ok());
// task status != Approved
let request = InvokeTaskRequest {
diff --git a/types/src/file.rs b/types/src/file.rs
index 085dfe8..80b2795 100644
--- a/types/src/file.rs
+++ b/types/src/file.rs
@@ -14,10 +14,11 @@
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
+use crate::storage::Storable;
use crate::TeaclaveFileCryptoInfo;
-use anyhow;
+use anyhow::{anyhow, Result};
use serde::{Deserialize, Serialize};
-use serde_json;
+use std::collections::HashSet;
use std::prelude::v1::*;
use url::Url;
use uuid::Uuid;
@@ -34,7 +35,16 @@ pub struct TeaclaveInputFile {
pub url: Url,
pub hash: String,
pub crypto_info: TeaclaveFileCryptoInfo,
- pub owner: String,
+ pub owner: HashSet<String>,
+ pub uuid: Uuid,
+}
+
+#[derive(Debug, Deserialize, Serialize)]
+pub struct TeaclaveOutputFile {
+ pub url: Url,
+ pub hash: Option<String>,
+ pub crypto_info: TeaclaveFileCryptoInfo,
+ pub owner: HashSet<String>,
pub uuid: Uuid,
}
@@ -43,7 +53,7 @@ impl TeaclaveInputFile {
url: Url,
hash: String,
crypto_info: TeaclaveFileCryptoInfo,
- owner: String,
+ owner: HashSet<String>,
) -> TeaclaveInputFile {
TeaclaveInputFile {
url,
@@ -53,37 +63,18 @@ impl TeaclaveInputFile {
uuid: create_uuid(),
}
}
-}
-
-pub trait Storable: Serialize + for<'de> Deserialize<'de> {
- fn key_prefix() -> &'static str;
-
- fn uuid(&self) -> Uuid;
-
- fn key_string(&self) -> String {
- format!("{}-{}", Self::key_prefix(), self.uuid().to_string())
- }
-
- fn key(&self) -> Vec<u8> {
- self.key_string().into_bytes()
- }
- fn match_prefix(key: &str) -> bool {
- key.starts_with(Self::key_prefix())
- }
-
- fn to_vec(&self) -> anyhow::Result<Vec<u8>> {
- let bytes = serde_json::to_vec(self)?;
- Ok(bytes)
- }
-
- fn from_slice(bytes: &[u8]) -> anyhow::Result<Self> {
- let obj = serde_json::from_slice(bytes)?;
- Ok(obj)
- }
-
- fn external_id(&self) -> String {
- self.key_string()
+ pub fn from_output(output: TeaclaveOutputFile) ->
Result<TeaclaveInputFile> {
+ let input = TeaclaveInputFile {
+ url: output.url,
+ hash: output
+ .hash
+ .ok_or_else(|| anyhow!("output is not finished"))?,
+ crypto_info: output.crypto_info,
+ owner: output.owner,
+ uuid: output.uuid,
+ };
+ Ok(input)
}
}
@@ -97,27 +88,12 @@ impl Storable for TeaclaveInputFile {
}
}
-impl Storable for TeaclaveOutputFile {
- fn key_prefix() -> &'static str {
- OUTPUT_FILE_PREFIX
- }
-
- fn uuid(&self) -> Uuid {
- self.uuid
- }
-}
-
-#[derive(Debug, Deserialize, Serialize)]
-pub struct TeaclaveOutputFile {
- pub url: Url,
- pub hash: Option<String>,
- pub crypto_info: TeaclaveFileCryptoInfo,
- pub owner: String,
- pub uuid: Uuid,
-}
-
impl TeaclaveOutputFile {
- pub fn new(url: Url, crypto_info: TeaclaveFileCryptoInfo, owner: String)
-> TeaclaveOutputFile {
+ pub fn new(
+ url: Url,
+ crypto_info: TeaclaveFileCryptoInfo,
+ owner: HashSet<String>,
+ ) -> TeaclaveOutputFile {
TeaclaveOutputFile {
url,
hash: None,
@@ -126,4 +102,29 @@ impl TeaclaveOutputFile {
uuid: create_uuid(),
}
}
+
+ pub fn new_fusion_data(owner: HashSet<String>) ->
Result<TeaclaveOutputFile> {
+ let uuid = create_uuid();
+ let url = format!("fusion://path/{}?token=fusion_token",
uuid.to_string());
+ let url = Url::parse(&url).map_err(|_| anyhow!("invalid url"))?;
+ let crypto_info = TeaclaveFileCryptoInfo::default();
+
+ Ok(TeaclaveOutputFile {
+ url,
+ hash: None,
+ crypto_info,
+ owner,
+ uuid,
+ })
+ }
+}
+
+impl Storable for TeaclaveOutputFile {
+ fn key_prefix() -> &'static str {
+ OUTPUT_FILE_PREFIX
+ }
+
+ fn uuid(&self) -> Uuid {
+ self.uuid
+ }
}
diff --git a/types/src/function.rs b/types/src/function.rs
new file mode 100644
index 0000000..a125825
--- /dev/null
+++ b/types/src/function.rs
@@ -0,0 +1,58 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you 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.
+
+use crate::Storable;
+use serde::{Deserialize, Serialize};
+use std::prelude::v1::*;
+use uuid::Uuid;
+
+#[derive(Debug, Deserialize, Serialize)]
+pub struct FunctionInput {
+ pub name: String,
+ pub description: String,
+}
+
+#[derive(Debug, Deserialize, Serialize)]
+pub struct FunctionOutput {
+ pub name: String,
+ pub description: String,
+}
+
+const FUNCION_PREFIX: &str = "function";
+#[derive(Debug, Deserialize, Serialize)]
+pub struct Function {
+ pub function_id: Uuid,
+ pub name: String,
+ pub description: String,
+ pub payload: Vec<u8>,
+ pub is_public: bool,
+ pub arg_list: Vec<String>,
+ pub input_list: Vec<FunctionInput>,
+ pub output_list: Vec<FunctionOutput>,
+ pub owner: String,
+ pub is_native: bool,
+}
+
+impl Storable for Function {
+ fn key_prefix() -> &'static str {
+ FUNCION_PREFIX
+ }
+
+ fn uuid(&self) -> Uuid {
+ self.function_id
+ }
+}
diff --git a/types/src/lib.rs b/types/src/lib.rs
index 282014c..a459022 100644
--- a/types/src/lib.rs
+++ b/types/src/lib.rs
@@ -21,6 +21,14 @@ mod worker;
pub use worker::*;
mod file;
pub use file::*;
+mod function;
+pub use function::*;
+mod staged_task;
+pub use staged_task::*;
+mod storage;
+pub use storage::Storable;
+mod task;
+pub use task::*;
/// Status for Ecall
#[repr(C)]
diff --git a/types/src/staged_task.rs b/types/src/staged_task.rs
new file mode 100644
index 0000000..3c846be
--- /dev/null
+++ b/types/src/staged_task.rs
@@ -0,0 +1,84 @@
+use crate::{Function, Storable, TeaclaveFileCryptoInfo, TeaclaveInputFile,
TeaclaveOutputFile};
+use serde::{Deserialize, Serialize};
+use std::collections::HashMap;
+use std::prelude::v1::*;
+use url::Url;
+use uuid::Uuid;
+
+const STAGED_TASK_PREFIX: &str = "staged-"; // staged-task-uuid
+pub const QUEUE_KEY: &str = "staged-task";
+
+#[derive(Debug, Deserialize, Serialize)]
+pub struct InputData {
+ pub url: Url,
+ pub hash: String,
+ pub crypto_info: TeaclaveFileCryptoInfo,
+}
+
+#[derive(Debug, Deserialize, Serialize)]
+pub struct OutputData {
+ pub url: Url,
+ pub crypto_info: TeaclaveFileCryptoInfo,
+}
+
+#[derive(Debug, Deserialize, Serialize)]
+pub struct StagedTask {
+ pub task_id: Uuid,
+ pub function_id: String,
+ pub function_payload: Vec<u8>,
+ pub arg_list: HashMap<String, String>,
+ pub input_map: HashMap<String, InputData>,
+ pub output_map: HashMap<String, OutputData>,
+}
+
+impl Storable for StagedTask {
+ fn key_prefix() -> &'static str {
+ STAGED_TASK_PREFIX
+ }
+
+ fn uuid(&self) -> Uuid {
+ self.task_id
+ }
+}
+
+impl InputData {
+ pub fn from_input_file(file: TeaclaveInputFile) -> InputData {
+ InputData {
+ url: file.url,
+ hash: file.hash,
+ crypto_info: file.crypto_info,
+ }
+ }
+}
+
+impl OutputData {
+ pub fn from_output_file(file: TeaclaveOutputFile) -> OutputData {
+ OutputData {
+ url: file.url,
+ crypto_info: file.crypto_info,
+ }
+ }
+}
+
+impl StagedTask {
+ pub fn new(
+ task_id: Uuid,
+ function: Function,
+ arg_list: HashMap<String, String>,
+ input_map: HashMap<String, InputData>,
+ output_map: HashMap<String, OutputData>,
+ ) -> Self {
+ Self {
+ task_id: task_id.to_owned(),
+ function_id: function.external_id(),
+ function_payload: function.payload,
+ arg_list,
+ input_map,
+ output_map,
+ }
+ }
+
+ pub fn get_queue_key() -> &'static str {
+ QUEUE_KEY
+ }
+}
diff --git a/types/src/storage.rs b/types/src/storage.rs
new file mode 100644
index 0000000..778681e
--- /dev/null
+++ b/types/src/storage.rs
@@ -0,0 +1,37 @@
+use anyhow;
+use serde::{Deserialize, Serialize};
+use serde_json;
+use std::prelude::v1::*;
+use uuid::Uuid;
+
+pub trait Storable: Serialize + for<'de> Deserialize<'de> {
+ fn key_prefix() -> &'static str;
+
+ fn uuid(&self) -> Uuid;
+
+ fn key_string(&self) -> String {
+ format!("{}-{}", Self::key_prefix(), self.uuid().to_string())
+ }
+
+ fn key(&self) -> Vec<u8> {
+ self.key_string().into_bytes()
+ }
+
+ fn match_prefix(key: &str) -> bool {
+ key.starts_with(Self::key_prefix())
+ }
+
+ fn to_vec(&self) -> anyhow::Result<Vec<u8>> {
+ let bytes = serde_json::to_vec(self)?;
+ Ok(bytes)
+ }
+
+ fn from_slice(bytes: &[u8]) -> anyhow::Result<Self> {
+ let obj = serde_json::from_slice(bytes)?;
+ Ok(obj)
+ }
+
+ fn external_id(&self) -> String {
+ self.key_string()
+ }
+}
diff --git a/types/src/task.rs b/types/src/task.rs
new file mode 100644
index 0000000..013cf71
--- /dev/null
+++ b/types/src/task.rs
@@ -0,0 +1,48 @@
+use crate::Storable;
+use serde::{Deserialize, Serialize};
+use std::collections::{HashMap, HashSet};
+use std::prelude::v1::*;
+use uuid::Uuid;
+
+#[derive(Debug, Deserialize, Serialize, Clone)]
+pub struct DataOwnerList {
+ pub user_id_list: HashSet<String>,
+}
+
+#[derive(Debug, Deserialize, Serialize, std::cmp::PartialEq)]
+pub enum TaskStatus {
+ Created,
+ Ready,
+ Approved,
+ Running,
+ Failed,
+ Finished,
+}
+
+const TASK_PREFIX: &str = "task-";
+
+#[derive(Debug, Deserialize, Serialize)]
+pub struct Task {
+ pub task_id: Uuid,
+ pub creator: String,
+ pub function_id: String,
+ pub function_owner: String,
+ pub arg_list: HashMap<String, String>,
+ pub input_data_owner_list: HashMap<String, DataOwnerList>,
+ pub output_data_owner_list: HashMap<String, DataOwnerList>,
+ pub participants: HashSet<String>,
+ pub approved_user_list: HashSet<String>,
+ pub input_map: HashMap<String, String>,
+ pub output_map: HashMap<String, String>,
+ pub status: TaskStatus,
+}
+
+impl Storable for Task {
+ fn key_prefix() -> &'static str {
+ TASK_PREFIX
+ }
+
+ fn uuid(&self) -> Uuid {
+ self.task_id
+ }
+}
diff --git a/types/src/worker.rs b/types/src/worker.rs
index 16981b3..351ff09 100644
--- a/types/src/worker.rs
+++ b/types/src/worker.rs
@@ -55,13 +55,13 @@ impl std::fmt::Display for TeaclaveExecutorSelector {
}
#[derive(Debug)]
-pub struct InputData {
+pub struct WorkerInputData {
pub path: std::path::PathBuf,
pub hash: String,
pub crypto_info: TeaclaveFileCryptoInfo,
}
#[derive(Debug)]
-pub struct OutputData {
+pub struct WorkerOutputData {
pub path: std::path::PathBuf,
pub hash: String,
pub crypto_info: TeaclaveFileCryptoInfo,
@@ -157,7 +157,7 @@ pub fn read_all_bytes(path: impl AsRef<std::path::Path>) ->
anyhow::Result<Vec<u
}
pub fn convert_encrypted_input_file(
- src: InputData,
+ src: WorkerInputData,
dst: &str,
) -> anyhow::Result<TeaclaveWorkerInputFileInfo> {
let path = src.path;
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]