You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@teaclave.apache.org by hs...@apache.org on 2023/03/17 13:27:08 UTC

[incubator-teaclave] branch master updated (d02fb0ce -> 37d8895e)

This is an automated email from the ASF dual-hosted git repository.

hsun pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-teaclave.git


    from d02fb0ce Improve function arguments by introducing FunctionArgument
     new e35d1fcf Update the Rustfmt edition number to the latest
     new 45f728f7 [CI] Update the license tool
     new d3d48ad8 Reorganize scripts and tool
     new 37d8895e Add usage statistics and quota for function

The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .github/workflows/ci.yml                           |   2 +-
 .rustfmt.toml                                      |   2 +-
 README.md                                          |   2 +-
 cmake/TeaclaveGenVars.cmake                        |   2 +-
 cmake/scripts/parse_cargo_packages.py              |   4 +-
 cmake/tomls/Cargo.sgx_trusted_lib.toml             |   2 +-
 cmake/tomls/Cargo.sgx_untrusted_app.toml           |   2 +-
 docs/README.md                                     |   2 +-
 docs/development-tips.md                           |   2 +-
 examples/c/builtin_echo.c                          |   3 +-
 examples/c/builtin_ordered_set_intersect.c         |   3 +-
 examples/rust/builtin_echo/src/main.rs             |   1 +
 .../rust/builtin_ordered_set_intersect/src/main.rs |   1 +
 sdk/c/teaclave_client_sdk.h                        |  26 +++++
 sdk/python/teaclave.py                             |  35 +++++-
 sdk/rust/src/bindings.rs                           |   5 +
 sdk/rust/src/lib.rs                                |  74 ++++++++++++-
 services/frontend/enclave/src/service.rs           |  34 ++++--
 services/management/enclave/src/error.rs           |   2 +
 services/management/enclave/src/lib.rs             |   1 +
 services/management/enclave/src/service.rs         | 118 ++++++++++++++++++---
 .../src/proto/teaclave_frontend_service.proto      |  12 +++
 .../src/proto/teaclave_management_service.proto    |   1 +
 services/proto/src/teaclave_frontend_service.rs    |  83 ++++++++++++++-
 services/proto/src/teaclave_management_service.rs  |   4 +
 tests/functional/enclave/src/management_service.rs |   1 +
 tools/README.md                                    |   9 ++
 {scripts => tools/scripts}/ide.sh                  |   0
 {tool => tools/sgx_tool}/README.md                 |   4 -
 {tool => tools/sgx_tool}/app/Cargo.toml            |   4 +-
 {tool => tools/sgx_tool}/app/build.rs              |   0
 {tool => tools/sgx_tool}/app/src/main.rs           |   0
 {tool => tools/sgx_tool}/enclave/Cargo.toml        |   8 +-
 .../sgx_tool}/enclave/Enclave.config.xml           |   0
 {tool => tools/sgx_tool}/enclave/src/lib.rs        |   0
 types/src/function.rs                              |  29 +++++
 36 files changed, 424 insertions(+), 54 deletions(-)
 create mode 100644 tools/README.md
 rename {scripts => tools/scripts}/ide.sh (100%)
 rename {tool => tools/sgx_tool}/README.md (97%)
 rename {tool => tools/sgx_tool}/app/Cargo.toml (89%)
 rename {tool => tools/sgx_tool}/app/build.rs (100%)
 rename {tool => tools/sgx_tool}/app/src/main.rs (100%)
 rename {tool => tools/sgx_tool}/enclave/Cargo.toml (85%)
 rename {tool => tools/sgx_tool}/enclave/Enclave.config.xml (100%)
 rename {tool => tools/sgx_tool}/enclave/src/lib.rs (100%)


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@teaclave.apache.org
For additional commands, e-mail: commits-help@teaclave.apache.org


[incubator-teaclave] 03/04: Reorganize scripts and tool

Posted by hs...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

hsun pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-teaclave.git

commit d3d48ad854f271f94d2fe992e79cc06a16a7e123
Author: sunhe05 <su...@baidu.com>
AuthorDate: Mon Mar 13 08:09:58 2023 +0000

    Reorganize scripts and tool
---
 README.md                                           | 2 +-
 cmake/TeaclaveGenVars.cmake                         | 2 +-
 cmake/scripts/parse_cargo_packages.py               | 4 ++--
 cmake/tomls/Cargo.sgx_trusted_lib.toml              | 2 +-
 cmake/tomls/Cargo.sgx_untrusted_app.toml            | 2 +-
 docs/README.md                                      | 2 +-
 docs/development-tips.md                            | 2 +-
 tools/README.md                                     | 9 +++++++++
 {scripts => tools/scripts}/ide.sh                   | 0
 {tool => tools/sgx_tool}/README.md                  | 4 ----
 {tool => tools/sgx_tool}/app/Cargo.toml             | 4 ++--
 {tool => tools/sgx_tool}/app/build.rs               | 0
 {tool => tools/sgx_tool}/app/src/main.rs            | 0
 {tool => tools/sgx_tool}/enclave/Cargo.toml         | 8 ++++----
 {tool => tools/sgx_tool}/enclave/Enclave.config.xml | 0
 {tool => tools/sgx_tool}/enclave/src/lib.rs         | 0
 16 files changed, 23 insertions(+), 18 deletions(-)

diff --git a/README.md b/README.md
index beb2f234..d0c9b86d 100644
--- a/README.md
+++ b/README.md
@@ -81,7 +81,7 @@ platform, making computation on privacy-sensitive data safe and simple.
 - [Teaclave Worker](worker)
 - [Test Harness and Test Cases](tests)
 - [Third-Party Dependency Vendoring](third_party)
-- [Tool](tool)
+- [Tools](tools)
 - [Types](types)
 
 ### API References
diff --git a/cmake/TeaclaveGenVars.cmake b/cmake/TeaclaveGenVars.cmake
index 2ccbb63d..68773be6 100644
--- a/cmake/TeaclaveGenVars.cmake
+++ b/cmake/TeaclaveGenVars.cmake
@@ -24,7 +24,7 @@ set(TEACLAVE_SERVICE_INSTALL_DIR ${TEACLAVE_INSTALL_DIR}/services)
 set(TEACLAVE_EXAMPLE_INSTALL_DIR ${TEACLAVE_INSTALL_DIR}/examples)
 set(TEACLAVE_BIN_INSTALL_DIR ${TEACLAVE_INSTALL_DIR}/bin)
 set(TEACLAVE_CLI_INSTALL_DIR ${TEACLAVE_INSTALL_DIR}/cli)
-set(TEACLAVE_TOOL_INSTALL_DIR ${TEACLAVE_INSTALL_DIR}/tool)
+set(TEACLAVE_TOOL_INSTALL_DIR ${TEACLAVE_INSTALL_DIR}/tools)
 set(TEACLAVE_DCAP_INSTALL_DIR ${TEACLAVE_INSTALL_DIR}/dcap)
 set(TEACLAVE_LIB_INSTALL_DIR ${TEACLAVE_INSTALL_DIR}/lib)
 set(TEACLAVE_DOC_INSTALL_DIR ${TEACLAVE_INSTALL_DIR}/docs)
diff --git a/cmake/scripts/parse_cargo_packages.py b/cmake/scripts/parse_cargo_packages.py
index 457b9c77..2337473b 100644
--- a/cmake/scripts/parse_cargo_packages.py
+++ b/cmake/scripts/parse_cargo_packages.py
@@ -80,8 +80,8 @@ def pkg_path_2_category(pkg_path):
         return 'examples'
     elif pkg_path.startswith('tests/'):
         return 'tests'
-    elif pkg_path.startswith('tool/'):
-        return 'tool'
+    elif pkg_path.startswith('tools/'):
+        return 'tools'
     elif pkg_path == 'cli':
         return 'cli'
     elif pkg_path == 'dcap':
diff --git a/cmake/tomls/Cargo.sgx_trusted_lib.toml b/cmake/tomls/Cargo.sgx_trusted_lib.toml
index 74396e75..b07e2c81 100644
--- a/cmake/tomls/Cargo.sgx_trusted_lib.toml
+++ b/cmake/tomls/Cargo.sgx_trusted_lib.toml
@@ -28,7 +28,7 @@ members = [
   "tests/unit/enclave",
   "tests/functional/enclave",
   "tests/integration/enclave",
-  "tool/enclave",
+  "tools/sgx_tool/enclave",
 ]
 
 exclude = [
diff --git a/cmake/tomls/Cargo.sgx_untrusted_app.toml b/cmake/tomls/Cargo.sgx_untrusted_app.toml
index 6f3b3ce2..017840a9 100644
--- a/cmake/tomls/Cargo.sgx_untrusted_app.toml
+++ b/cmake/tomls/Cargo.sgx_untrusted_app.toml
@@ -29,7 +29,7 @@ members = [
   "tests/unit/app",
   "tests/functional/app",
   "tests/integration/app",
-  "tool/app",
+  "tools/sgx_tool/app",
 ]
 
 exclude = [
diff --git a/docs/README.md b/docs/README.md
index 0366c56e..09ded691 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -51,7 +51,7 @@ permalink: /docs/
 - [Teaclave Worker](../worker/README.md)
 - [Test Harness and Test Cases](../tests/README.md)
 - [Third-Party Dependency Vendoring](../third_party/README.md)
-- [Tool](../tool/README.md)
+- [Tools](../tools/README.md)
 - [Types](../types/README.md)
 
 ## API References
diff --git a/docs/development-tips.md b/docs/development-tips.md
index 6659b0c5..b9bb2296 100644
--- a/docs/development-tips.md
+++ b/docs/development-tips.md
@@ -35,7 +35,7 @@ applications such as CLI, no `Cargo.toml` is needed. After the preparation of
 will see type hints and cross references using IDEs with extensions.
 
 ::: tip NOTE 
-You can also simply use the script `scripts/ide.sh <trusted|untrusted|clean>`
+You can also simply use the script `tools/scripts/ide.sh <trusted|untrusted|clean>`
 to prepare a IDE-friendly developing environment for trusted
 part, untrusetd part, or remove the files generated by this script. 
 :::
diff --git a/tools/README.md b/tools/README.md
new file mode 100644
index 00000000..f64f0195
--- /dev/null
+++ b/tools/README.md
@@ -0,0 +1,9 @@
+---
+permalink: /docs/codebase/tools
+---
+
+# Tools
+
+This directory contains help tools:
+- scripts: tools in the script form
+- sgx_tool: Teaclave SGX Tool
diff --git a/scripts/ide.sh b/tools/scripts/ide.sh
similarity index 100%
rename from scripts/ide.sh
rename to tools/scripts/ide.sh
diff --git a/tool/README.md b/tools/sgx_tool/README.md
similarity index 97%
rename from tool/README.md
rename to tools/sgx_tool/README.md
index 48dc6044..329cfd85 100644
--- a/tool/README.md
+++ b/tools/sgx_tool/README.md
@@ -1,7 +1,3 @@
----
-permalink: /docs/codebase/tool
----
-
 # Teaclave SGX Tool
 
 This tool is to dump some SGX related information, e.g., hardware and software
diff --git a/tool/app/Cargo.toml b/tools/sgx_tool/app/Cargo.toml
similarity index 89%
rename from tool/app/Cargo.toml
rename to tools/sgx_tool/app/Cargo.toml
index f29d9fd5..65cd3ac3 100644
--- a/tool/app/Cargo.toml
+++ b/tools/sgx_tool/app/Cargo.toml
@@ -33,7 +33,7 @@ serde_json       = { version = "1.0.39" }
 raw-cpuid = "8.1.0"
 structopt = "0.3"
 
-teaclave_binder            = { path = "../../binder", features = ["app"] }
-teaclave_types             = { path = "../../types", features = ["app"] }
+teaclave_binder            = { path = "../../../binder", features = ["app"] }
+teaclave_types             = { path = "../../../types", features = ["app"] }
 
 sgx_types = { version = "2.0.0" }
diff --git a/tool/app/build.rs b/tools/sgx_tool/app/build.rs
similarity index 100%
rename from tool/app/build.rs
rename to tools/sgx_tool/app/build.rs
diff --git a/tool/app/src/main.rs b/tools/sgx_tool/app/src/main.rs
similarity index 100%
rename from tool/app/src/main.rs
rename to tools/sgx_tool/app/src/main.rs
diff --git a/tool/enclave/Cargo.toml b/tools/sgx_tool/enclave/Cargo.toml
similarity index 85%
rename from tool/enclave/Cargo.toml
rename to tools/sgx_tool/enclave/Cargo.toml
index 69ef3d76..188ff171 100644
--- a/tool/enclave/Cargo.toml
+++ b/tools/sgx_tool/enclave/Cargo.toml
@@ -46,10 +46,10 @@ base64           = { version = "0.13.0" }
 thiserror   = { version = "1.0.9" }
 
 
-teaclave_attestation           = { path = "../../attestation" }
-teaclave_binder                = { path = "../../binder" }
-teaclave_service_enclave_utils = { path = "../../services/utils/service_enclave_utils" }
-teaclave_types                 = { path = "../../types" }
+teaclave_attestation           = { path = "../../../attestation" }
+teaclave_binder                = { path = "../../../binder" }
+teaclave_service_enclave_utils = { path = "../../../services/utils/service_enclave_utils" }
+teaclave_types                 = { path = "../../../types" }
 
 [target.'cfg(not(target_vendor = "teaclave"))'.dependencies]
 sgx_types = { version = "2.0.0" }
diff --git a/tool/enclave/Enclave.config.xml b/tools/sgx_tool/enclave/Enclave.config.xml
similarity index 100%
rename from tool/enclave/Enclave.config.xml
rename to tools/sgx_tool/enclave/Enclave.config.xml
diff --git a/tool/enclave/src/lib.rs b/tools/sgx_tool/enclave/src/lib.rs
similarity index 100%
rename from tool/enclave/src/lib.rs
rename to tools/sgx_tool/enclave/src/lib.rs


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@teaclave.apache.org
For additional commands, e-mail: commits-help@teaclave.apache.org


[incubator-teaclave] 04/04: Add usage statistics and quota for function

Posted by hs...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

hsun pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-teaclave.git

commit 37d8895e284780b7745fbec46a8126cbd4c93b43
Author: sunhe05 <su...@baidu.com>
AuthorDate: Tue Mar 14 09:44:12 2023 +0000

    Add usage statistics and quota for function
---
 examples/c/builtin_echo.c                          |   3 +-
 examples/c/builtin_ordered_set_intersect.c         |   3 +-
 examples/rust/builtin_echo/src/main.rs             |   1 +
 .../rust/builtin_ordered_set_intersect/src/main.rs |   1 +
 sdk/c/teaclave_client_sdk.h                        |  26 +++++
 sdk/python/teaclave.py                             |  35 +++++-
 sdk/rust/src/bindings.rs                           |   5 +
 sdk/rust/src/lib.rs                                |  74 ++++++++++++-
 services/frontend/enclave/src/service.rs           |  34 ++++--
 services/management/enclave/src/error.rs           |   2 +
 services/management/enclave/src/lib.rs             |   1 +
 services/management/enclave/src/service.rs         | 118 ++++++++++++++++++---
 .../src/proto/teaclave_frontend_service.proto      |  12 +++
 .../src/proto/teaclave_management_service.proto    |   1 +
 services/proto/src/teaclave_frontend_service.rs    |  83 ++++++++++++++-
 services/proto/src/teaclave_management_service.rs  |   4 +
 tests/functional/enclave/src/management_service.rs |   1 +
 types/src/function.rs                              |  29 +++++
 18 files changed, 399 insertions(+), 34 deletions(-)

diff --git a/examples/c/builtin_echo.c b/examples/c/builtin_echo.c
index 9a838356..0fed2594 100644
--- a/examples/c/builtin_echo.c
+++ b/examples/c/builtin_echo.c
@@ -37,7 +37,8 @@ const char *register_function_request_serialized = QUOTE({
     "arguments" : [{"key": "message", "default_value": "", "allow_overwrite": true}],
     "inputs" : [],
     "outputs" : [],
-    "user_allowlist": []
+    "user_allowlist": [],
+    "usage_quota": -1
 });
 
 const char *create_task_request_serialized = QUOTE({
diff --git a/examples/c/builtin_ordered_set_intersect.c b/examples/c/builtin_ordered_set_intersect.c
index 2b278202..70037e13 100644
--- a/examples/c/builtin_ordered_set_intersect.c
+++ b/examples/c/builtin_ordered_set_intersect.c
@@ -69,7 +69,8 @@ const char *register_function_request_serialized = QUOTE(
         {"name": "output_result1", "description": "Output data.", "optional": false},
         {"name": "output_result2", "description": "Output data.", "optional": false}
     ],
-    "user_allowlist": ["user0", "user1"]
+    "user_allowlist": ["user0", "user1"],
+    "usage_quota": -1
 });
 
 const char *create_task_request_serialized = QUOTE(
diff --git a/examples/rust/builtin_echo/src/main.rs b/examples/rust/builtin_echo/src/main.rs
index 378b43ba..f595274d 100644
--- a/examples/rust/builtin_echo/src/main.rs
+++ b/examples/rust/builtin_echo/src/main.rs
@@ -69,6 +69,7 @@ fn echo(message: &str) -> Result<Vec<u8>> {
         )]),
         None,
         None,
+        None,
     )?;
 
     println!(
diff --git a/examples/rust/builtin_ordered_set_intersect/src/main.rs b/examples/rust/builtin_ordered_set_intersect/src/main.rs
index d39127d4..75ead1f6 100644
--- a/examples/rust/builtin_ordered_set_intersect/src/main.rs
+++ b/examples/rust/builtin_ordered_set_intersect/src/main.rs
@@ -130,6 +130,7 @@ impl Client {
                 teaclave_client_sdk::FunctionOutput::new("output_result1", "Output data.", false),
                 teaclave_client_sdk::FunctionOutput::new("output_result2", "Output data.", false),
             ]),
+            None,
         )?;
         self.client.get_function(&function_id)?;
         let function_arguments = hashmap!("order" => "ascending", "save_log" => "true"); // Order can be ascending or desending
diff --git a/sdk/c/teaclave_client_sdk.h b/sdk/c/teaclave_client_sdk.h
index affaa623..95519a4a 100644
--- a/sdk/c/teaclave_client_sdk.h
+++ b/sdk/c/teaclave_client_sdk.h
@@ -307,6 +307,32 @@ int teaclave_get_function_serialized(struct FrontendClient *client,
                                      char *serialized_response,
                                      size_t *serialized_response_len);
 
+/**
+ * Send JSON serialized request to the service with the `client` and
+ * get the serialized response.
+ *
+ * # Arguments
+ *
+ * * `client`: service client.
+ * * `serialized_request`; JSON serialized request
+ * * `serialized_response`: buffer to store the JSON serialized response.
+ * * `serialized_response_len`: length of the allocated
+ *   `serialized_response`, will be set as the length of
+ *   `serialized_response` when return successfully.
+ *
+ * # Return
+ *
+ * The function returns 0 for success. On error, the function returns 1.
+ *
+ * # Safety
+ *
+ * Inconsistent length of allocated buffer may caused overflow.
+ */
+int teaclave_get_function_usage_stats_serialized(struct FrontendClient *client,
+                                                 const char *serialized_request,
+                                                 char *serialized_response,
+                                                 size_t *serialized_response_len);
+
 /**
  * Send JSON serialized request to the service with the `client` and
  * get the serialized response.
diff --git a/sdk/python/teaclave.py b/sdk/python/teaclave.py
index c4a4873c..1dad6159 100644
--- a/sdk/python/teaclave.py
+++ b/sdk/python/teaclave.py
@@ -568,7 +568,7 @@ class RegisterFunctionRequest(Request):
                  executor_type: str, public: bool, payload: List[int],
                  arguments: List[FunctionArgument],
                  inputs: List[FunctionInput], outputs: List[FunctionOutput],
-                 user_allowlist: List[str]):
+                 user_allowlist: List[str], usage_quota: int):
         self.request = "register_function"
         self.metadata = metadata
         self.name = name
@@ -580,6 +580,7 @@ class RegisterFunctionRequest(Request):
         self.inputs = inputs
         self.outputs = outputs
         self.user_allowlist = user_allowlist
+        self.usage_quota = usage_quota
 
 
 class UpdateFunctionRequest(Request):
@@ -588,7 +589,7 @@ class UpdateFunctionRequest(Request):
                  description: str, executor_type: str, public: bool,
                  payload: List[int], arguments: List[FunctionArgument],
                  inputs: List[FunctionInput], outputs: List[FunctionOutput],
-                 user_allowlist: List[str]):
+                 user_allowlist: List[str], usage_quota: int):
         self.request = "update_function"
         self.metadata = metadata
         self.function_id = function_id
@@ -601,6 +602,7 @@ class UpdateFunctionRequest(Request):
         self.inputs = inputs
         self.outputs = outputs
         self.user_allowlist = user_allowlist
+        self.usage_quota = usage_quota
 
 
 class ListFunctionsRequest(Request):
@@ -635,6 +637,14 @@ class GetFunctionRequest(Request):
         self.function_id = function_id
 
 
+class GetFunctionUsageStatsRequest(Request):
+
+    def __init__(self, metadata: Metadata, function_id: str):
+        self.request = "get_function_usage_stats"
+        self.metadata = metadata
+        self.function_id = function_id
+
+
 class RegisterInputFileRequest(Request):
 
     def __init__(self, metadata: Metadata, url: str, cmac: List[int],
@@ -763,13 +773,14 @@ class FrontendService(TeaclaveService):
         inputs: List[FunctionInput] = [],
         outputs: List[FunctionOutput] = [],
         user_allowlist: List[str] = [],
+        usage_quota: int = -1,
     ):
         self.check_metadata()
         self.check_channel()
         request = RegisterFunctionRequest(self.metadata, name, description,
                                           executor_type, public, payload,
                                           arguments, inputs, outputs,
-                                          user_allowlist)
+                                          user_allowlist, usage_quota)
         _write_message(self.channel, request)
         response = _read_message(self.channel)
         if response["result"] == "ok":
@@ -792,13 +803,14 @@ class FrontendService(TeaclaveService):
         inputs: List[FunctionInput] = [],
         outputs: List[FunctionOutput] = [],
         user_allowlist: List[str] = [],
+        usage_quota: int = -1,
     ):
         self.check_metadata()
         self.check_channel()
         request = UpdateFunctionRequest(self.metadata, function_id, name,
                                         description, executor_type, public,
                                         payload, arguments, inputs, outputs,
-                                        user_allowlist)
+                                        user_allowlist, usage_quota)
         _write_message(self.channel, request)
         response = _read_message(self.channel)
         if response["result"] == "ok":
@@ -834,6 +846,21 @@ class FrontendService(TeaclaveService):
                 reason = response["request_error"]
             raise TeaclaveException(f"Failed to get function ({reason})")
 
+    def get_function_usage_stats(self, user_id: str, function_id: str):
+        self.check_metadata()
+        self.check_channel()
+        request = GetFunctionUsageStatsRequest(self.metadata, function_id)
+        _write_message(self.channel, request)
+        response = _read_message(self.channel)
+        if response["result"] == "ok":
+            return response["content"]
+        else:
+            reason = "unknown"
+            if "request_error" in response:
+                reason = response["request_error"]
+            raise TeaclaveException(
+                f"Failed to get function usage statistics ({reason})")
+
     def delete_function(self, function_id: str):
         self.check_metadata()
         self.check_channel()
diff --git a/sdk/rust/src/bindings.rs b/sdk/rust/src/bindings.rs
index 5b388ed3..f48b8c71 100644
--- a/sdk/rust/src/bindings.rs
+++ b/sdk/rust/src/bindings.rs
@@ -460,6 +460,11 @@ generate_function_serialized!(
     teaclave_get_function_serialized,
     get_function_serialized
 );
+generate_function_serialized!(
+    FrontendClient,
+    teaclave_get_function_usage_stats_serialized,
+    get_function_usage_stats_serialized
+);
 generate_function_serialized!(
     FrontendClient,
     teaclave_register_input_file_serialized,
diff --git a/sdk/rust/src/lib.rs b/sdk/rust/src/lib.rs
index 65d80fed..a212624e 100644
--- a/sdk/rust/src/lib.rs
+++ b/sdk/rust/src/lib.rs
@@ -35,13 +35,15 @@ pub use teaclave_proto::teaclave_frontend_service::GetFunctionResponse as Functi
 pub use teaclave_proto::teaclave_frontend_service::{
     ApproveTaskRequest, ApproveTaskResponse, AssignDataRequest, AssignDataResponse,
     CancelTaskRequest, CancelTaskResponse, CreateTaskRequest, CreateTaskResponse,
-    GetFunctionRequest, GetFunctionResponse, GetTaskRequest, GetTaskResponse, InvokeTaskRequest,
+    GetFunctionRequest, GetFunctionResponse, GetFunctionUsageStatsRequest,
+    GetFunctionUsageStatsResponse, GetTaskRequest, GetTaskResponse, InvokeTaskRequest,
     InvokeTaskResponse, RegisterFunctionRequest, RegisterFunctionRequestBuilder,
     RegisterFunctionResponse, RegisterInputFileRequest, RegisterInputFileResponse,
     RegisterOutputFileRequest, RegisterOutputFileResponse,
 };
 pub use teaclave_types::{
-    EnclaveInfo, Executor, FileCrypto, FunctionArgument, FunctionInput, FunctionOutput, TaskResult,
+    EnclaveInfo, Executor, FileCrypto, FunctionArgument, FunctionInput, FunctionOutput,
+    FunctionUsage, TaskResult,
 };
 
 pub mod bindings;
@@ -214,6 +216,7 @@ impl FrontendClient {
         arguments: Option<Vec<FunctionArgument>>,
         inputs: Option<Vec<FunctionInput>>,
         outputs: Option<Vec<FunctionOutput>>,
+        usage_quota: Option<i32>,
     ) -> Result<String> {
         let executor_type = executor_type.try_into()?;
         let mut builder = RegisterFunctionRequestBuilder::new()
@@ -233,6 +236,10 @@ impl FrontendClient {
         if let Some(outputs) = outputs {
             builder = builder.outputs(outputs);
         }
+        if let Some(usage_quota) = usage_quota {
+            let usage_quota = (usage_quota >= 0).then_some(usage_quota);
+            builder = builder.usage_quota(usage_quota)
+        }
 
         let request = builder.build();
         let response = self.register_function_with_request(request)?;
@@ -266,6 +273,37 @@ impl FrontendClient {
         Ok(response)
     }
 
+    pub fn get_function_usage_stats_serialized(
+        &mut self,
+        serialized_request: &str,
+    ) -> Result<String> {
+        let request: frontend_proto::GetFunctionUsageStatsRequest =
+            serde_json::from_str(serialized_request)?;
+        let response: frontend_proto::GetFunctionUsageStatsResponse = self
+            .get_function_usage_stats_with_request(request.try_into()?)?
+            .into();
+        let serialized_response = serde_json::to_string(&response)?;
+
+        Ok(serialized_response)
+    }
+
+    pub fn get_function_usage_stats(&mut self, function_id: &str) -> Result<i32> {
+        let function_id = function_id.try_into()?;
+        let request = GetFunctionUsageStatsRequest::new(function_id);
+        let response = self.get_function_usage_stats_with_request(request)?;
+
+        Ok(response.current_usage)
+    }
+
+    pub fn get_function_usage_stats_with_request(
+        &mut self,
+        request: GetFunctionUsageStatsRequest,
+    ) -> Result<GetFunctionUsageStatsResponse> {
+        let response = self.api_client.get_function_usage_stats(request)?;
+
+        Ok(response)
+    }
+
     pub fn register_input_file_with_request(
         &mut self,
         request: RegisterInputFileRequest,
@@ -595,6 +633,7 @@ mod tests {
                 Some(vec![FunctionArgument::new("message", "", true)]),
                 None,
                 None,
+                Some(2),
             )
             .unwrap();
         let _ = client.get_function(&function_id).unwrap();
@@ -602,7 +641,7 @@ mod tests {
         let task_id = client
             .create_task(
                 &function_id,
-                Some(function_arguments),
+                Some(function_arguments.clone()),
                 "builtin",
                 None,
                 None,
@@ -611,8 +650,37 @@ mod tests {
 
         let _ = client.invoke_task(&task_id).unwrap();
         let (result, log) = client.get_task_result(&task_id).unwrap();
+        let usage_number = client.get_function_usage_stats(&function_id).unwrap();
         assert_eq!(result, b"Hello, Teaclave!");
         assert!(log.is_empty());
+        assert_eq!(1, usage_number);
+
+        let task_id = client
+            .create_task(
+                &function_id,
+                Some(function_arguments.clone()),
+                "builtin",
+                None,
+                None,
+            )
+            .unwrap();
+        let _ = client.invoke_task(&task_id).unwrap();
+        let (result, log) = client.get_task_result(&task_id).unwrap();
+        let usage_number = client.get_function_usage_stats(&function_id).unwrap();
+        assert_eq!(result, b"Hello, Teaclave!");
+        assert!(log.is_empty());
+        assert_eq!(2, usage_number);
+
+        let task_id = client
+            .create_task(
+                &function_id,
+                Some(function_arguments),
+                "builtin",
+                None,
+                None,
+            )
+            .unwrap();
+        assert!(client.invoke_task(&task_id).is_err());
     }
 
     #[test]
diff --git a/services/frontend/enclave/src/service.rs b/services/frontend/enclave/src/service.rs
index b59bdd5e..bc072769 100644
--- a/services/frontend/enclave/src/service.rs
+++ b/services/frontend/enclave/src/service.rs
@@ -31,15 +31,15 @@ use teaclave_proto::teaclave_frontend_service::{
     ApproveTaskRequest, ApproveTaskResponse, AssignDataRequest, AssignDataResponse,
     CancelTaskRequest, CancelTaskResponse, CreateTaskRequest, CreateTaskResponse,
     DeleteFunctionRequest, DeleteFunctionResponse, DisableFunctionRequest, DisableFunctionResponse,
-    GetFunctionRequest, GetFunctionResponse, GetInputFileRequest, GetInputFileResponse,
-    GetOutputFileRequest, GetOutputFileResponse, GetTaskRequest, GetTaskResponse,
-    InvokeTaskRequest, InvokeTaskResponse, ListFunctionsRequest, ListFunctionsResponse,
-    RegisterFunctionRequest, RegisterFunctionResponse, RegisterFusionOutputRequest,
-    RegisterFusionOutputResponse, RegisterInputFileRequest, RegisterInputFileResponse,
-    RegisterInputFromOutputRequest, RegisterInputFromOutputResponse, RegisterOutputFileRequest,
-    RegisterOutputFileResponse, TeaclaveFrontend, UpdateFunctionRequest, UpdateFunctionResponse,
-    UpdateInputFileRequest, UpdateInputFileResponse, UpdateOutputFileRequest,
-    UpdateOutputFileResponse,
+    GetFunctionRequest, GetFunctionResponse, GetFunctionUsageStatsRequest,
+    GetFunctionUsageStatsResponse, GetInputFileRequest, GetInputFileResponse, GetOutputFileRequest,
+    GetOutputFileResponse, GetTaskRequest, GetTaskResponse, InvokeTaskRequest, InvokeTaskResponse,
+    ListFunctionsRequest, ListFunctionsResponse, RegisterFunctionRequest, RegisterFunctionResponse,
+    RegisterFusionOutputRequest, RegisterFusionOutputResponse, RegisterInputFileRequest,
+    RegisterInputFileResponse, RegisterInputFromOutputRequest, RegisterInputFromOutputResponse,
+    RegisterOutputFileRequest, RegisterOutputFileResponse, TeaclaveFrontend, UpdateFunctionRequest,
+    UpdateFunctionResponse, UpdateInputFileRequest, UpdateInputFileResponse,
+    UpdateOutputFileRequest, UpdateOutputFileResponse,
 };
 use teaclave_proto::teaclave_management_service::TeaclaveManagementClient;
 use teaclave_rpc::endpoint::Endpoint;
@@ -108,6 +108,7 @@ enum Endpoints {
     GetInputFile,
     RegisterFunction,
     GetFunction,
+    GetFunctionUsageStats,
     UpdateFunction,
     ListFunctions,
     DeleteFunction,
@@ -149,7 +150,7 @@ fn authorize(claims: &UserAuthClaims, request: Endpoints) -> bool {
         | Endpoints::ApproveTask
         | Endpoints::InvokeTask
         | Endpoints::CancelTask => role.is_data_owner(),
-        Endpoints::GetFunction | Endpoints::ListFunctions => {
+        Endpoints::GetFunction | Endpoints::ListFunctions | Endpoints::GetFunctionUsageStats => {
             role.is_function_owner() || role.is_data_owner()
         }
     }
@@ -271,6 +272,7 @@ impl TeaclaveFrontend for TeaclaveFrontendService {
             Endpoints::RegisterInputFromOutput
         )
     }
+
     fn get_output_file(
         &self,
         request: Request<GetOutputFileRequest>,
@@ -331,6 +333,18 @@ impl TeaclaveFrontend for TeaclaveFrontendService {
         )
     }
 
+    fn get_function_usage_stats(
+        &self,
+        request: Request<GetFunctionUsageStatsRequest>,
+    ) -> TeaclaveServiceResponseResult<GetFunctionUsageStatsResponse> {
+        authentication_and_forward_to_management!(
+            self,
+            request,
+            get_function_usage_stats,
+            Endpoints::GetFunctionUsageStats
+        )
+    }
+
     fn delete_function(
         &self,
         request: Request<DeleteFunctionRequest>,
diff --git a/services/management/enclave/src/error.rs b/services/management/enclave/src/error.rs
index 1df0b992..ed330144 100644
--- a/services/management/enclave/src/error.rs
+++ b/services/management/enclave/src/error.rs
@@ -46,6 +46,8 @@ pub(crate) enum ManagementServiceError {
     TaskInvokeError,
     #[error("failed to cancel task, reason: {0}")]
     TaskCancelError(String),
+    #[error("function quota has been used up")]
+    FunctionQuotaError,
 }
 
 impl From<ManagementServiceError> for TeaclaveServiceResponseError {
diff --git a/services/management/enclave/src/lib.rs b/services/management/enclave/src/lib.rs
index c98f698a..66a4ec0b 100644
--- a/services/management/enclave/src/lib.rs
+++ b/services/management/enclave/src/lib.rs
@@ -140,6 +140,7 @@ pub mod tests {
             service::tests::handle_input_file,
             service::tests::handle_output_file,
             service::tests::handle_function,
+            service::tests::check_function_quota,
             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 1557de35..2cb4b4f8 100644
--- a/services/management/enclave/src/service.rs
+++ b/services/management/enclave/src/service.rs
@@ -23,15 +23,15 @@ use teaclave_proto::teaclave_frontend_service::{
     ApproveTaskRequest, ApproveTaskResponse, AssignDataRequest, AssignDataResponse,
     CancelTaskRequest, CancelTaskResponse, CreateTaskRequest, CreateTaskResponse,
     DeleteFunctionRequest, DeleteFunctionResponse, DisableFunctionRequest, DisableFunctionResponse,
-    GetFunctionRequest, GetFunctionResponse, GetInputFileRequest, GetInputFileResponse,
-    GetOutputFileRequest, GetOutputFileResponse, GetTaskRequest, GetTaskResponse,
-    InvokeTaskRequest, InvokeTaskResponse, ListFunctionsRequest, ListFunctionsResponse,
-    RegisterFunctionRequest, RegisterFunctionResponse, RegisterFusionOutputRequest,
-    RegisterFusionOutputResponse, RegisterInputFileRequest, RegisterInputFileResponse,
-    RegisterInputFromOutputRequest, RegisterInputFromOutputResponse, RegisterOutputFileRequest,
-    RegisterOutputFileResponse, UpdateFunctionRequest, UpdateFunctionResponse,
-    UpdateInputFileRequest, UpdateInputFileResponse, UpdateOutputFileRequest,
-    UpdateOutputFileResponse,
+    GetFunctionRequest, GetFunctionResponse, GetFunctionUsageStatsRequest,
+    GetFunctionUsageStatsResponse, GetInputFileRequest, GetInputFileResponse, GetOutputFileRequest,
+    GetOutputFileResponse, GetTaskRequest, GetTaskResponse, InvokeTaskRequest, InvokeTaskResponse,
+    ListFunctionsRequest, ListFunctionsResponse, RegisterFunctionRequest, RegisterFunctionResponse,
+    RegisterFusionOutputRequest, RegisterFusionOutputResponse, RegisterInputFileRequest,
+    RegisterInputFileResponse, RegisterInputFromOutputRequest, RegisterInputFromOutputResponse,
+    RegisterOutputFileRequest, RegisterOutputFileResponse, UpdateFunctionRequest,
+    UpdateFunctionResponse, UpdateInputFileRequest, UpdateInputFileResponse,
+    UpdateOutputFileRequest, UpdateOutputFileResponse,
 };
 use teaclave_proto::teaclave_management_service::TeaclaveManagement;
 use teaclave_proto::teaclave_storage_service::{
@@ -297,6 +297,12 @@ impl TeaclaveManagement for TeaclaveManagementService {
             }
         }
 
+        let usage = FunctionUsage {
+            function_id: function.id,
+            ..Default::default()
+        };
+        self.write_to_db(&usage)?;
+
         let response = RegisterFunctionResponse::new(function.external_id());
         Ok(response)
     }
@@ -364,6 +370,42 @@ impl TeaclaveManagement for TeaclaveManagementService {
         }
     }
 
+    // access control:
+    // function.public || request.role == PlatformAdmin || requested user_id in the user_allowlist
+    fn get_function_usage_stats(
+        &self,
+        request: Request<GetFunctionUsageStatsRequest>,
+    ) -> TeaclaveServiceResponseResult<GetFunctionUsageStatsResponse> {
+        let user_id = get_request_user_id(&request)?;
+        let role = get_request_role(&request)?;
+        let request = request.message;
+        let function: Function = self
+            .read_from_db(&request.function_id)
+            .map_err(|_| ManagementServiceError::InvalidFunctionId)?;
+
+        ensure!(
+            function.public
+                || role == UserRole::PlatformAdmin
+                || function.user_allowlist.contains(&user_id.to_string()),
+            ManagementServiceError::PermissionDenied
+        );
+
+        let usage = FunctionUsage {
+            function_id: function.id,
+            ..Default::default()
+        };
+        let external_id = usage.external_id();
+        let function_usage = self
+            .read_from_db::<FunctionUsage>(&external_id)
+            .map_err(|_| ManagementServiceError::InvalidFunctionId)?;
+        let function_quota = function.usage_quota.unwrap_or(-1);
+        let response = GetFunctionUsageStatsResponse {
+            function_quota,
+            current_usage: function_usage.use_numbers,
+        };
+        Ok(response)
+    }
+
     // access control: function.owner == user_id
     fn delete_function(
         &self,
@@ -692,6 +734,22 @@ impl TeaclaveManagement for TeaclaveManagementService {
 
         log::debug!("InvokeTask: get function: {:?}", function);
 
+        let usage = FunctionUsage {
+            function_id: function.id,
+            ..Default::default()
+        };
+        let external_id = usage.external_id();
+        let mut function_usage = self
+            .read_from_db::<FunctionUsage>(&external_id)
+            .map_err(|_| ManagementServiceError::InvalidFunctionId)?;
+        let function_current_use_numbers = function_usage.use_numbers;
+
+        if let Some(quota) = function.usage_quota {
+            if quota <= function_current_use_numbers {
+                return Err(ManagementServiceError::FunctionQuotaError.into());
+            }
+        }
+
         let mut task: Task<Stage> = ts.try_into().map_err(|e| {
             log::warn!("Stage state error: {:?}", e);
             ManagementServiceError::TaskInvokeError
@@ -707,6 +765,8 @@ impl TeaclaveManagement for TeaclaveManagementService {
         let ts: TaskState = task.into();
         self.write_to_db(&ts)?;
 
+        function_usage.use_numbers = function_current_use_numbers + 1;
+        self.write_to_db(&function_usage)?;
         Ok(InvokeTaskResponse)
     }
 
@@ -894,8 +954,9 @@ impl TeaclaveManagementService {
         let function_arg1 = FunctionArgument::new("arg1", "", true);
         let function_arg2 = FunctionArgument::new("arg2", "", true);
 
+        let function_id = Uuid::parse_str("00000000-0000-0000-0000-000000000001").unwrap();
         let function = FunctionBuilder::new()
-            .id(Uuid::parse_str("00000000-0000-0000-0000-000000000001").unwrap())
+            .id(function_id)
             .name("mock-func-1")
             .description("mock-desc")
             .payload(b"mock-payload".to_vec())
@@ -906,12 +967,20 @@ impl TeaclaveManagementService {
             .owner("teaclave".to_string())
             .build();
 
+        let function_usage = FunctionUsage {
+            function_id,
+            use_numbers: 0,
+        };
+
         self.write_to_db(&function)?;
+        self.write_to_db(&function_usage)?;
 
         let function_output = FunctionOutput::new("output", "output_desc", false);
         let function_arg1 = FunctionArgument::new("arg1", "", true);
+        let function_id = Uuid::parse_str("00000000-0000-0000-0000-000000000002").unwrap();
+
         let function = FunctionBuilder::new()
-            .id(Uuid::parse_str("00000000-0000-0000-0000-000000000002").unwrap())
+            .id(function_id)
             .name("mock-func-2")
             .description("mock-desc")
             .payload(b"mock-payload".to_vec())
@@ -921,10 +990,17 @@ impl TeaclaveManagementService {
             .owner("teaclave".to_string())
             .build();
 
+        let function_usage = FunctionUsage {
+            function_id,
+            use_numbers: 0,
+        };
+
         self.write_to_db(&function)?;
+        self.write_to_db(&function_usage)?;
 
+        let function_id = Uuid::parse_str("00000000-0000-0000-0000-000000000003").unwrap();
         let function = FunctionBuilder::new()
-            .id(Uuid::parse_str("00000000-0000-0000-0000-000000000003").unwrap())
+            .id(function_id)
             .name("mock-func-3")
             .description("Private mock function")
             .payload(b"mock-payload".to_vec())
@@ -934,7 +1010,14 @@ impl TeaclaveManagementService {
             .user_allowlist(vec!["mock_user".to_string(), "mock_user1".to_string()])
             .build();
 
+        let function_usage = FunctionUsage {
+            function_id,
+            use_numbers: 0,
+        };
+
         self.write_to_db(&function)?;
+        self.write_to_db(&function_usage)?;
+
         Ok(())
     }
 }
@@ -1016,6 +1099,17 @@ pub mod tests {
         debug!("function: {:?}", deserialized_function);
     }
 
+    pub fn check_function_quota() {
+        let function = FunctionBuilder::new().build();
+        assert_eq!(function.usage_quota, None);
+
+        let function = FunctionBuilder::new().usage_quota(Some(-5)).build();
+        assert_eq!(function.usage_quota, None);
+
+        let function = FunctionBuilder::new().usage_quota(Some(5)).build();
+        assert_eq!(function.usage_quota, Some(5));
+    }
+
     pub fn handle_task() {
         let function_arg = FunctionArgument::new("arg", "", true);
         let function = FunctionBuilder::new()
diff --git a/services/proto/src/proto/teaclave_frontend_service.proto b/services/proto/src/proto/teaclave_frontend_service.proto
index afd0dbb4..07c23987 100644
--- a/services/proto/src/proto/teaclave_frontend_service.proto
+++ b/services/proto/src/proto/teaclave_frontend_service.proto
@@ -128,6 +128,7 @@ message RegisterFunctionRequest {
   repeated FunctionInput inputs = 10;
   repeated FunctionOutput outputs = 11;
   repeated string user_allowlist = 12;
+  int32 usage_quota = 13;
 }
 
 message RegisterFunctionResponse {
@@ -145,6 +146,7 @@ message UpdateFunctionRequest {
   repeated FunctionInput inputs = 10;
   repeated FunctionOutput outputs = 11;
   repeated string user_allowlist = 12;
+  int32 usage_quota = 13;
 }
 
 message UpdateFunctionResponse {
@@ -168,6 +170,15 @@ message GetFunctionResponse {
   repeated string user_allowlist = 12;
 }
 
+message GetFunctionUsageStatsRequest {
+  string function_id = 1;
+}
+
+message GetFunctionUsageStatsResponse {
+  int32 function_quota = 1;
+  int32 current_usage = 2;
+}
+
 message DeleteFunctionRequest {
   string function_id = 1;
 }
@@ -264,6 +275,7 @@ service TeaclaveFrontend {
   rpc GetInputFile (GetInputFileRequest) returns (GetInputFileResponse);
   rpc RegisterFunction (RegisterFunctionRequest) returns (RegisterFunctionResponse);
   rpc GetFunction (GetFunctionRequest) returns (GetFunctionResponse);
+  rpc GetFunctionUsageStats (GetFunctionUsageStatsRequest) returns (GetFunctionUsageStatsResponse);
   rpc UpdateFunction (UpdateFunctionRequest) returns (UpdateFunctionResponse);
   rpc ListFunctions (ListFunctionsRequest) returns (ListFunctionsResponse);
   rpc DeleteFunction (DeleteFunctionRequest) returns (DeleteFunctionResponse);
diff --git a/services/proto/src/proto/teaclave_management_service.proto b/services/proto/src/proto/teaclave_management_service.proto
index d79bd42e..7d9639ab 100644
--- a/services/proto/src/proto/teaclave_management_service.proto
+++ b/services/proto/src/proto/teaclave_management_service.proto
@@ -36,6 +36,7 @@ service TeaclaveManagement {
   rpc RegisterFunction (teaclave_frontend_service_proto.RegisterFunctionRequest) returns (teaclave_frontend_service_proto.RegisterFunctionResponse);
   rpc UpdateFunction (teaclave_frontend_service_proto.UpdateFunctionRequest) returns (teaclave_frontend_service_proto.UpdateFunctionResponse);
   rpc GetFunction (teaclave_frontend_service_proto.GetFunctionRequest) returns (teaclave_frontend_service_proto.GetFunctionResponse);
+  rpc GetFunctionUsageStats (teaclave_frontend_service_proto.GetFunctionUsageStatsRequest) returns (teaclave_frontend_service_proto.GetFunctionUsageStatsResponse);
   rpc DeleteFunction (teaclave_frontend_service_proto.DeleteFunctionRequest) returns (teaclave_frontend_service_proto.DeleteFunctionResponse);
   rpc DisableFunction (teaclave_frontend_service_proto.DisableFunctionRequest) returns (teaclave_frontend_service_proto.DisableFunctionResponse);
   rpc ListFunctions (teaclave_frontend_service_proto.ListFunctionsRequest) returns (teaclave_frontend_service_proto.ListFunctionsResponse);
diff --git a/services/proto/src/teaclave_frontend_service.rs b/services/proto/src/teaclave_frontend_service.rs
index 2e3c9150..ce3c26cc 100644
--- a/services/proto/src/teaclave_frontend_service.rs
+++ b/services/proto/src/teaclave_frontend_service.rs
@@ -288,6 +288,7 @@ pub struct RegisterFunctionRequest {
     pub inputs: Vec<FunctionInput>,
     pub outputs: Vec<FunctionOutput>,
     pub user_allowlist: Vec<String>,
+    pub usage_quota: Option<i32>,
 }
 
 #[derive(Default)]
@@ -351,6 +352,11 @@ impl RegisterFunctionRequestBuilder {
         self
     }
 
+    pub fn usage_quota(mut self, usage_quota: Option<i32>) -> Self {
+        self.request.usage_quota = usage_quota;
+        self
+    }
+
     pub fn build(self) -> RegisterFunctionRequest {
         self.request
     }
@@ -369,6 +375,7 @@ impl From<RegisterFunctionRequest> for FunctionBuilder {
             .inputs(request.inputs)
             .outputs(request.outputs)
             .user_allowlist(request.user_allowlist)
+            .usage_quota(request.usage_quota)
     }
 }
 
@@ -398,6 +405,7 @@ pub struct UpdateFunctionRequest {
     pub inputs: Vec<FunctionInput>,
     pub outputs: Vec<FunctionOutput>,
     pub user_allowlist: Vec<String>,
+    pub usage_quota: Option<i32>,
 }
 
 #[derive(Default)]
@@ -466,6 +474,11 @@ impl UpdateFunctionRequestBuilder {
         self
     }
 
+    pub fn usage_quota(mut self, usage_quota: Option<i32>) -> Self {
+        self.request.usage_quota = usage_quota;
+        self
+    }
+
     pub fn build(self) -> UpdateFunctionRequest {
         self.request
     }
@@ -485,6 +498,7 @@ impl From<UpdateFunctionRequest> for FunctionBuilder {
             .inputs(request.inputs)
             .outputs(request.outputs)
             .user_allowlist(request.user_allowlist)
+            .usage_quota(request.usage_quota)
     }
 }
 
@@ -528,6 +542,26 @@ pub struct GetFunctionResponse {
     pub user_allowlist: Vec<String>,
 }
 
+#[into_request(TeaclaveManagementRequest::GetFunctionUsageStats)]
+#[into_request(TeaclaveFrontendRequest::GetFunctionUsageStats)]
+#[derive(Debug)]
+pub struct GetFunctionUsageStatsRequest {
+    pub function_id: ExternalID,
+}
+
+impl GetFunctionUsageStatsRequest {
+    pub fn new(function_id: ExternalID) -> Self {
+        Self { function_id }
+    }
+}
+
+#[into_request(TeaclaveManagementResponse::GetFunctionUsageStats)]
+#[derive(Debug)]
+pub struct GetFunctionUsageStatsResponse {
+    pub function_quota: i32,
+    pub current_usage: i32,
+}
+
 #[into_request(TeaclaveManagementRequest::DeleteFunction)]
 #[into_request(TeaclaveFrontendRequest::DeleteFunction)]
 #[derive(Debug)]
@@ -1123,6 +1157,8 @@ impl std::convert::TryFrom<proto::RegisterFunctionRequest> for RegisterFunctionR
             .map(FunctionArgument::try_from)
             .collect();
 
+        let usage_quota = (proto.usage_quota >= 0).then_some(proto.usage_quota);
+
         let ret = Self {
             name: proto.name,
             description: proto.description,
@@ -1133,6 +1169,7 @@ impl std::convert::TryFrom<proto::RegisterFunctionRequest> for RegisterFunctionR
             inputs: inputs?,
             outputs: outputs?,
             user_allowlist: proto.user_allowlist,
+            usage_quota,
         };
         Ok(ret)
     }
@@ -1166,6 +1203,7 @@ impl From<RegisterFunctionRequest> for proto::RegisterFunctionRequest {
             inputs,
             outputs,
             user_allowlist: request.user_allowlist,
+            usage_quota: request.usage_quota.unwrap_or(-1),
         }
     }
 }
@@ -1175,9 +1213,7 @@ impl std::convert::TryFrom<proto::RegisterFunctionResponse> for RegisterFunction
 
     fn try_from(proto: proto::RegisterFunctionResponse) -> Result<Self> {
         let function_id = proto.function_id.try_into()?;
-        let ret = Self { function_id };
-
-        Ok(ret)
+        Ok(Self { function_id })
     }
 }
 
@@ -1211,6 +1247,8 @@ impl std::convert::TryFrom<proto::UpdateFunctionRequest> for UpdateFunctionReque
             .map(FunctionArgument::try_from)
             .collect();
 
+        let usage_quota = (proto.usage_quota >= 0).then_some(proto.usage_quota);
+
         let ret = Self {
             function_id,
             name: proto.name,
@@ -1222,6 +1260,7 @@ impl std::convert::TryFrom<proto::UpdateFunctionRequest> for UpdateFunctionReque
             inputs: inputs?,
             outputs: outputs?,
             user_allowlist: proto.user_allowlist,
+            usage_quota,
         };
         Ok(ret)
     }
@@ -1256,6 +1295,7 @@ impl From<UpdateFunctionRequest> for proto::UpdateFunctionRequest {
             inputs,
             outputs,
             user_allowlist: request.user_allowlist,
+            usage_quota: request.usage_quota.unwrap_or(-1),
         }
     }
 }
@@ -1298,6 +1338,43 @@ impl From<GetFunctionRequest> for proto::GetFunctionRequest {
     }
 }
 
+impl From<GetFunctionUsageStatsRequest> for proto::GetFunctionUsageStatsRequest {
+    fn from(request: GetFunctionUsageStatsRequest) -> Self {
+        Self {
+            function_id: request.function_id.to_string(),
+        }
+    }
+}
+
+impl std::convert::TryFrom<proto::GetFunctionUsageStatsRequest> for GetFunctionUsageStatsRequest {
+    type Error = Error;
+
+    fn try_from(proto: proto::GetFunctionUsageStatsRequest) -> Result<Self> {
+        let function_id: ExternalID = proto.function_id.try_into()?;
+        Ok(Self { function_id })
+    }
+}
+
+impl From<GetFunctionUsageStatsResponse> for proto::GetFunctionUsageStatsResponse {
+    fn from(request: GetFunctionUsageStatsResponse) -> Self {
+        Self {
+            function_quota: request.function_quota,
+            current_usage: request.current_usage,
+        }
+    }
+}
+
+impl std::convert::TryFrom<proto::GetFunctionUsageStatsResponse> for GetFunctionUsageStatsResponse {
+    type Error = Error;
+
+    fn try_from(proto: proto::GetFunctionUsageStatsResponse) -> Result<Self> {
+        Ok(Self {
+            function_quota: proto.function_quota,
+            current_usage: proto.current_usage,
+        })
+    }
+}
+
 impl std::convert::TryFrom<proto::DeleteFunctionResponse> for DeleteFunctionResponse {
     type Error = Error;
 
diff --git a/services/proto/src/teaclave_management_service.rs b/services/proto/src/teaclave_management_service.rs
index 6f8cbcb0..e9612eaf 100644
--- a/services/proto/src/teaclave_management_service.rs
+++ b/services/proto/src/teaclave_management_service.rs
@@ -50,6 +50,10 @@ pub type UpdateFunctionRequest = crate::teaclave_frontend_service::UpdateFunctio
 pub type UpdateFunctionRequestBuilder =
     crate::teaclave_frontend_service::UpdateFunctionRequestBuilder;
 pub type UpdateFunctionResponse = crate::teaclave_frontend_service::UpdateFunctionResponse;
+pub type GetFunctionUsageStatsRequest =
+    crate::teaclave_frontend_service::GetFunctionUsageStatsRequest;
+pub type GetFunctionUsageStatsResponse =
+    crate::teaclave_frontend_service::GetFunctionUsageStatsResponse;
 pub type DeleteFunctionRequest = crate::teaclave_frontend_service::DeleteFunctionRequest;
 pub type DeleteFunctionResponse = crate::teaclave_frontend_service::DeleteFunctionResponse;
 pub type DisableFunctionRequest = crate::teaclave_frontend_service::DisableFunctionRequest;
diff --git a/tests/functional/enclave/src/management_service.rs b/tests/functional/enclave/src/management_service.rs
index 95249edd..29b164cb 100644
--- a/tests/functional/enclave/src/management_service.rs
+++ b/tests/functional/enclave/src/management_service.rs
@@ -135,6 +135,7 @@ fn test_register_function() {
         .arguments(vec![FunctionArgument::new("arg", "", true)])
         .inputs(vec![function_input])
         .outputs(vec![function_output])
+        .usage_quota(Some(0))
         .build();
 
     let mut client = authorized_client("mock_user");
diff --git a/types/src/function.rs b/types/src/function.rs
index 0180d8e8..13e0f331 100644
--- a/types/src/function.rs
+++ b/types/src/function.rs
@@ -87,6 +87,7 @@ pub struct Function {
     pub outputs: Vec<FunctionOutput>,
     pub owner: UserID,
     pub user_allowlist: Vec<String>,
+    pub usage_quota: Option<i32>,
 }
 
 #[derive(Default)]
@@ -156,6 +157,16 @@ impl FunctionBuilder {
         self
     }
 
+    pub fn usage_quota(mut self, usage_quota: Option<i32>) -> Self {
+        let usage_quota = match usage_quota {
+            Some(quota) if quota < 0 => None,
+            _ => usage_quota,
+        };
+
+        self.function.usage_quota = usage_quota;
+        self
+    }
+
     pub fn build(self) -> Function {
         self.function
     }
@@ -191,3 +202,21 @@ impl FunctionArgument {
         }
     }
 }
+
+const FUNCION_USAGE_PREFIX: &str = "usage";
+
+#[derive(Default, Debug, Deserialize, Serialize)]
+pub struct FunctionUsage {
+    pub function_id: Uuid,
+    pub use_numbers: i32,
+}
+
+impl Storable for FunctionUsage {
+    fn key_prefix() -> &'static str {
+        FUNCION_USAGE_PREFIX
+    }
+
+    fn uuid(&self) -> Uuid {
+        self.function_id
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@teaclave.apache.org
For additional commands, e-mail: commits-help@teaclave.apache.org


[incubator-teaclave] 01/04: Update the Rustfmt edition number to the latest

Posted by hs...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

hsun pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-teaclave.git

commit e35d1fcf1785041d4e1678b76903730e441b8279
Author: sunhe05 <su...@baidu.com>
AuthorDate: Mon Mar 13 07:47:20 2023 +0000

    Update the Rustfmt edition number to the latest
---
 .rustfmt.toml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.rustfmt.toml b/.rustfmt.toml
index 48020c8d..c458cfb1 100644
--- a/.rustfmt.toml
+++ b/.rustfmt.toml
@@ -13,5 +13,5 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-edition = "2018"
+edition = "2021"
 use_field_init_shorthand = true


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@teaclave.apache.org
For additional commands, e-mail: commits-help@teaclave.apache.org


[incubator-teaclave] 02/04: [CI] Update the license tool

Posted by hs...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

hsun pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-teaclave.git

commit 45f728f76bd0c62fe0c85f4fd95c699a7cfc6a4a
Author: sunhe05 <su...@baidu.com>
AuthorDate: Mon Mar 13 10:38:31 2023 +0000

    [CI] Update the license tool
---
 .github/workflows/ci.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index cb3a90ba..b548bf7d 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -63,4 +63,4 @@ jobs:
     steps:
       - uses: actions/checkout@v3
       - name: Check License Header
-        uses: apache/skywalking-eyes@main 
+        uses: apache/skywalking-eyes@v0.4.0


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@teaclave.apache.org
For additional commands, e-mail: commits-help@teaclave.apache.org