Replace rpc with tonic grpc
diff --git a/cmake/tomls/Cargo.sgx_trusted_lib.lock b/cmake/tomls/Cargo.sgx_trusted_lib.lock
index 8f4d145..e26aec5 100644
--- a/cmake/tomls/Cargo.sgx_trusted_lib.lock
+++ b/cmake/tomls/Cargo.sgx_trusted_lib.lock
@@ -3,19 +3,58 @@
 version = 3
 
 [[package]]
-name = "aho-corasick"
-version = "0.7.20"
+name = "adler"
+version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"
+checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
+
+[[package]]
+name = "aho-corasick"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04"
 dependencies = [
  "memchr",
 ]
 
 [[package]]
 name = "anyhow"
-version = "1.0.68"
+version = "1.0.71"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61"
+checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
+
+[[package]]
+name = "async-stream"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51"
+dependencies = [
+ "async-stream-impl",
+ "futures-core",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "async-stream-impl"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193"
+dependencies = [
+ "proc-macro2 1.0.56",
+ "quote 1.0.27",
+ "syn 2.0.15",
+]
+
+[[package]]
+name = "async-trait"
+version = "0.1.68"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842"
+dependencies = [
+ "proc-macro2 1.0.56",
+ "quote 1.0.27",
+ "syn 2.0.15",
+]
 
 [[package]]
 name = "autocfg"
@@ -55,15 +94,15 @@
 
 [[package]]
 name = "bumpalo"
-version = "3.11.1"
+version = "3.12.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba"
+checksum = "3c6ed94e98ecff0c12dd1b04c15ec0d7d9458ca8fe806cea6f12954efe74c63b"
 
 [[package]]
 name = "bytemuck"
-version = "1.12.3"
+version = "1.13.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aaa3a8d9a1ca92e282c96a32d6511b695d7d994d1d102ba85d279f9b2756947f"
+checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea"
 
 [[package]]
 name = "byteorder"
@@ -73,15 +112,15 @@
 
 [[package]]
 name = "bytes"
-version = "1.3.0"
+version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c"
+checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
 
 [[package]]
 name = "cc"
-version = "1.0.78"
+version = "1.0.79"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d"
+checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
 
 [[package]]
 name = "cfg-if"
@@ -97,9 +136,9 @@
 
 [[package]]
 name = "chrono"
-version = "0.4.23"
+version = "0.4.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f"
+checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b"
 dependencies = [
  "num-integer",
  "num-traits",
@@ -123,9 +162,9 @@
 
 [[package]]
 name = "core-foundation-sys"
-version = "0.8.3"
+version = "0.8.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
+checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
 
 [[package]]
 name = "crc"
@@ -133,20 +172,29 @@
 source = "git+https://github.com/mrhooray/crc-rs?rev=86696be#86696be09b7605d27327bbe659ac6c0e990c267f"
 
 [[package]]
+name = "crc32fast"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
+dependencies = [
+ "cfg-if 1.0.0",
+]
+
+[[package]]
 name = "ctor"
 version = "0.1.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096"
 dependencies = [
- "quote 1.0.26",
- "syn 1.0.107",
+ "quote 1.0.27",
+ "syn 1.0.109",
 ]
 
 [[package]]
 name = "either"
-version = "1.8.0"
+version = "1.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
+checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
 
 [[package]]
 name = "encoding_rs"
@@ -168,13 +216,13 @@
 
 [[package]]
 name = "errno"
-version = "0.2.8"
+version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1"
+checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
 dependencies = [
  "errno-dragonfly",
  "libc",
- "winapi",
+ "windows-sys 0.48.0",
 ]
 
 [[package]]
@@ -197,6 +245,22 @@
 ]
 
 [[package]]
+name = "fixedbitset"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
+
+[[package]]
+name = "flate2"
+version = "1.0.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743"
+dependencies = [
+ "crc32fast",
+ "miniz_oxide",
+]
+
+[[package]]
 name = "fnv"
 version = "1.0.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -228,9 +292,9 @@
 
 [[package]]
 name = "futures"
-version = "0.3.26"
+version = "0.3.28"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "13e2792b0ff0340399d58445b88fd9770e3489eff258a4cbc1523418f12abf84"
+checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40"
 dependencies = [
  "futures-channel",
  "futures-core",
@@ -243,9 +307,9 @@
 
 [[package]]
 name = "futures-channel"
-version = "0.3.26"
+version = "0.3.28"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5"
+checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2"
 dependencies = [
  "futures-core",
  "futures-sink",
@@ -253,15 +317,15 @@
 
 [[package]]
 name = "futures-core"
-version = "0.3.26"
+version = "0.3.28"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608"
+checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c"
 
 [[package]]
 name = "futures-executor"
-version = "0.3.26"
+version = "0.3.28"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e8de0a35a6ab97ec8869e32a2473f4b1324459e14c29275d14b10cb1fd19b50e"
+checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0"
 dependencies = [
  "futures-core",
  "futures-task",
@@ -270,38 +334,38 @@
 
 [[package]]
 name = "futures-io"
-version = "0.3.26"
+version = "0.3.28"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531"
+checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964"
 
 [[package]]
 name = "futures-macro"
-version = "0.3.26"
+version = "0.3.28"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70"
+checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
 dependencies = [
  "proc-macro2 1.0.56",
- "quote 1.0.26",
- "syn 1.0.107",
+ "quote 1.0.27",
+ "syn 2.0.15",
 ]
 
 [[package]]
 name = "futures-sink"
-version = "0.3.26"
+version = "0.3.28"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364"
+checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e"
 
 [[package]]
 name = "futures-task"
-version = "0.3.26"
+version = "0.3.28"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366"
+checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65"
 
 [[package]]
 name = "futures-util"
-version = "0.3.26"
+version = "0.3.28"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1"
+checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533"
 dependencies = [
  "futures-channel",
  "futures-core",
@@ -341,20 +405,20 @@
 
 [[package]]
 name = "ghost"
-version = "0.1.7"
+version = "0.1.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41973d4c45f7a35af8753ba3457cc99d406d863941fd7f52663cff54a5ab99b3"
+checksum = "e77ac7b51b8e6313251737fcef4b1c01a2ea102bde68415b62c0ee9268fec357"
 dependencies = [
  "proc-macro2 1.0.56",
- "quote 1.0.26",
- "syn 1.0.107",
+ "quote 1.0.27",
+ "syn 2.0.15",
 ]
 
 [[package]]
 name = "h2"
-version = "0.3.16"
+version = "0.3.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5be7b54589b581f624f566bf5d8eb2bab1db736c51528720b6bd36b96b55924d"
+checksum = "17f8a914c2987b688368b5138aa05321db91f4090cf26118185672ad588bce21"
 dependencies = [
  "bytes",
  "fnv",
@@ -365,7 +429,7 @@
  "indexmap",
  "slab",
  "tokio",
- "tokio-util",
+ "tokio-util 0.7.8",
  "tracing",
 ]
 
@@ -380,6 +444,15 @@
 version = "0.12.0"
 
 [[package]]
+name = "heck"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
+dependencies = [
+ "unicode-segmentation",
+]
+
+[[package]]
 name = "hermit-abi"
 version = "0.1.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -389,6 +462,12 @@
 ]
 
 [[package]]
+name = "hermit-abi"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
+
+[[package]]
 name = "hex"
 version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -396,9 +475,9 @@
 
 [[package]]
 name = "http"
-version = "0.2.8"
+version = "0.2.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399"
+checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482"
 dependencies = [
  "bytes",
  "fnv",
@@ -430,9 +509,9 @@
 
 [[package]]
 name = "hyper"
-version = "0.14.25"
+version = "0.14.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc5e554ff619822309ffd57d8734d77cd5ce6238bc956f037ea06c58238c9899"
+checksum = "ab302d72a6f11a3b910431ff93aae7e773078c769f0a3ef15fb9ec692ed147d4"
 dependencies = [
  "bytes",
  "futures-channel",
@@ -453,6 +532,18 @@
 ]
 
 [[package]]
+name = "hyper-timeout"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1"
+dependencies = [
+ "hyper",
+ "pin-project-lite",
+ "tokio",
+ "tokio-io-timeout",
+]
+
+[[package]]
 name = "hyper-tls"
 version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -491,9 +582,9 @@
 
 [[package]]
 name = "indexmap"
-version = "1.9.2"
+version = "1.9.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
+checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
 dependencies = [
  "autocfg",
  "hashbrown",
@@ -532,25 +623,26 @@
 checksum = "7e41b53715c6f0c4be49510bb82dee2c1e51c8586d885abe65396e82ed518548"
 dependencies = [
  "proc-macro2 1.0.56",
- "quote 1.0.26",
- "syn 1.0.107",
+ "quote 1.0.27",
+ "syn 1.0.109",
 ]
 
 [[package]]
 name = "io-lifetimes"
-version = "1.0.6"
+version = "1.0.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cfa919a82ea574332e2de6e74b4c36e74d41982b335080fa59d4ef31be20fdf3"
+checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220"
 dependencies = [
+ "hermit-abi 0.3.1",
  "libc",
- "windows-sys 0.45.0",
+ "windows-sys 0.48.0",
 ]
 
 [[package]]
 name = "ipnet"
-version = "2.7.1"
+version = "2.7.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "30e22bd8629359895450b59ea7a776c850561b96a3b1d31321c1949d9e6c9146"
+checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f"
 
 [[package]]
 name = "itertools"
@@ -572,9 +664,9 @@
 
 [[package]]
 name = "itoa"
-version = "1.0.5"
+version = "1.0.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
+checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
 
 [[package]]
 name = "jpeg-decoder"
@@ -584,9 +676,9 @@
 
 [[package]]
 name = "js-sys"
-version = "0.3.60"
+version = "0.3.62"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47"
+checksum = "68c16e1bfd491478ab155fd8b4896b86f9ede344949b641e61501e07c2b8b4d5"
 dependencies = [
  "wasm-bindgen",
 ]
@@ -613,9 +705,9 @@
 
 [[package]]
 name = "libc"
-version = "0.2.139"
+version = "0.2.144"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
+checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1"
 
 [[package]]
 name = "libm"
@@ -625,9 +717,9 @@
 
 [[package]]
 name = "linux-raw-sys"
-version = "0.1.4"
+version = "0.3.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
+checksum = "ece97ea872ece730aed82664c424eb4c8291e1ff2480247ccf7409044bc6479f"
 
 [[package]]
 name = "log"
@@ -656,9 +748,18 @@
 
 [[package]]
 name = "mime"
-version = "0.3.16"
+version = "0.3.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
+checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
+
+[[package]]
+name = "miniz_oxide"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
+dependencies = [
+ "adler",
+]
 
 [[package]]
 name = "mio"
@@ -672,6 +773,12 @@
 ]
 
 [[package]]
+name = "multimap"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a"
+
+[[package]]
 name = "native-tls"
 version = "0.2.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -793,21 +900,21 @@
 version = "1.14.0"
 source = "git+https://github.com/apache/incubator-teaclave-crates#ede1f68d891798fe6cf995e33281f01d59be9320"
 dependencies = [
- "hermit-abi",
+ "hermit-abi 0.1.19",
  "libc",
 ]
 
 [[package]]
 name = "once_cell"
-version = "1.16.0"
+version = "1.17.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
+checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
 
 [[package]]
 name = "openssl"
-version = "0.10.45"
+version = "0.10.52"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b102428fd03bc5edf97f62620f7298614c45cedf287c271e7ed450bbaf83f2e1"
+checksum = "01b8574602df80f7b85fdfc5392fa884a4e3b3f4f35402c070ab34c3d3f78d56"
 dependencies = [
  "bitflags",
  "cfg-if 1.0.0",
@@ -820,13 +927,13 @@
 
 [[package]]
 name = "openssl-macros"
-version = "0.1.0"
+version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c"
+checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
 dependencies = [
  "proc-macro2 1.0.56",
- "quote 1.0.26",
- "syn 1.0.107",
+ "quote 1.0.27",
+ "syn 2.0.15",
 ]
 
 [[package]]
@@ -837,11 +944,10 @@
 
 [[package]]
 name = "openssl-sys"
-version = "0.9.80"
+version = "0.9.87"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23bbbf7854cd45b83958ebe919f0e8e516793727652e27fda10a8384cfc790b7"
+checksum = "8e17f59264b2809d77ae94f0e1ebabc434773f370d6ca667bd223ea10e06cc7e"
 dependencies = [
- "autocfg",
  "cc",
  "libc",
  "pkg-config",
@@ -866,6 +972,36 @@
 checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
 
 [[package]]
+name = "petgraph"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4"
+dependencies = [
+ "fixedbitset",
+ "indexmap",
+]
+
+[[package]]
+name = "pin-project"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc"
+dependencies = [
+ "pin-project-internal",
+]
+
+[[package]]
+name = "pin-project-internal"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55"
+dependencies = [
+ "proc-macro2 1.0.56",
+ "quote 1.0.27",
+ "syn 1.0.109",
+]
+
+[[package]]
 name = "pin-project-lite"
 version = "0.2.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -879,9 +1015,9 @@
 
 [[package]]
 name = "pkg-config"
-version = "0.3.26"
+version = "0.3.27"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
+checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
 
 [[package]]
 name = "ppv-lite86"
@@ -909,25 +1045,55 @@
 
 [[package]]
 name = "prost"
-version = "0.11.8"
+version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e48e50df39172a3e7eb17e14642445da64996989bc212b583015435d39a58537"
+checksum = "444879275cb4fd84958b1a1d5420d15e6fcf7c235fe47f053c9c2a80aceb6001"
 dependencies = [
  "bytes",
  "prost-derive",
 ]
 
 [[package]]
-name = "prost-derive"
-version = "0.11.8"
+name = "prost-build"
+version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ea9b0f8cbe5e15a8a042d030bd96668db28ecb567ec37d691971ff5731d2b1b"
+checksum = "62941722fb675d463659e49c4f3fe1fe792ff24fe5bbaa9c08cd3b98a1c354f5"
+dependencies = [
+ "bytes",
+ "heck",
+ "itertools 0.10.5",
+ "lazy_static",
+ "log",
+ "multimap",
+ "petgraph",
+ "prost",
+ "prost-types",
+ "regex",
+ "tempfile",
+ "which",
+]
+
+[[package]]
+name = "prost-derive"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f9cc1a3263e07e0bf68e96268f37665207b49560d98739662cdfaae215c720fe"
 dependencies = [
  "anyhow",
  "itertools 0.10.5",
  "proc-macro2 1.0.56",
- "quote 1.0.26",
- "syn 1.0.107",
+ "quote 1.0.27",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "prost-types"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "534b7a0e836e3c482d2693070f982e39e7611da9695d4d1f5a4b186b51faef0a"
+dependencies = [
+ "bytes",
+ "prost",
 ]
 
 [[package]]
@@ -941,9 +1107,9 @@
 
 [[package]]
 name = "quote"
-version = "1.0.26"
+version = "1.0.27"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
+checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500"
 dependencies = [
  "proc-macro2 1.0.56",
 ]
@@ -1011,18 +1177,18 @@
 
 [[package]]
 name = "redox_syscall"
-version = "0.2.16"
+version = "0.3.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
+checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
 dependencies = [
  "bitflags",
 ]
 
 [[package]]
 name = "regex"
-version = "1.7.0"
+version = "1.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a"
+checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370"
 dependencies = [
  "aho-corasick",
  "memchr",
@@ -1031,15 +1197,15 @@
 
 [[package]]
 name = "regex-syntax"
-version = "0.6.28"
+version = "0.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
+checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c"
 
 [[package]]
 name = "reqwest"
-version = "0.11.16"
+version = "0.11.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "27b71749df584b7f4cac2c426c127a7c785a5106cc98f7a8feb044115f0fa254"
+checksum = "13293b639a097af28fc8a90f22add145a9c954e49d77da06263d58cf44d5fb91"
 dependencies = [
  "base64 0.21.0",
  "bytes",
@@ -1064,7 +1230,7 @@
  "serde_urlencoded",
  "tokio",
  "tokio-native-tls",
- "tokio-util",
+ "tokio-util 0.7.8",
  "tower-service",
  "url",
  "wasm-bindgen",
@@ -1111,16 +1277,16 @@
 
 [[package]]
 name = "rustix"
-version = "0.36.9"
+version = "0.37.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd5c6ff11fecd55b40746d1995a02f2eb375bf8c00d192d521ee09f42bef37bc"
+checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d"
 dependencies = [
  "bitflags",
  "errno",
  "io-lifetimes",
  "libc",
  "linux-raw-sys",
- "windows-sys 0.45.0",
+ "windows-sys 0.48.0",
 ]
 
 [[package]]
@@ -1163,9 +1329,9 @@
 
 [[package]]
 name = "ryu"
-version = "1.0.12"
+version = "1.0.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde"
+checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
 
 [[package]]
 name = "schannel"
@@ -1211,29 +1377,29 @@
 
 [[package]]
 name = "serde"
-version = "1.0.151"
+version = "1.0.162"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "97fed41fc1a24994d044e6db6935e69511a1153b52c15eb42493b26fa87feba0"
+checksum = "71b2f6e1ab5c2b98c05f0f35b236b22e8df7ead6ffbf51d7808da7f8817e7ab6"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.151"
+version = "1.0.162"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "255abe9a125a985c05190d687b320c12f9b1f0b99445e608c21ba0782c719ad8"
+checksum = "a2a0814352fd64b58489904a44ea8d90cb1a91dcb6b4f5ebabc32c8318e93cb6"
 dependencies = [
  "proc-macro2 1.0.56",
- "quote 1.0.26",
- "syn 1.0.107",
+ "quote 1.0.27",
+ "syn 2.0.15",
 ]
 
 [[package]]
 name = "serde_json"
-version = "1.0.91"
+version = "1.0.96"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883"
+checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1"
 dependencies = [
  "itoa",
  "ryu",
@@ -1319,8 +1485,8 @@
 version = "2.0.0"
 dependencies = [
  "proc-macro2 1.0.56",
- "quote 1.0.26",
- "syn 1.0.107",
+ "quote 1.0.27",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -1523,12 +1689,23 @@
 
 [[package]]
 name = "syn"
-version = "1.0.107"
+version = "1.0.109"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
 dependencies = [
  "proc-macro2 1.0.56",
- "quote 1.0.26",
+ "quote 1.0.27",
+ "unicode-ident",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822"
+dependencies = [
+ "proc-macro2 1.0.56",
+ "quote 1.0.27",
  "unicode-ident",
 ]
 
@@ -1553,6 +1730,7 @@
  "teaclave_test_utils",
  "teaclave_types",
  "thiserror",
+ "tokio",
 ]
 
 [[package]]
@@ -1611,6 +1789,7 @@
  "teaclave_test_utils",
  "teaclave_types",
  "thiserror",
+ "tokio",
  "uuid",
 ]
 
@@ -1688,6 +1867,7 @@
  "teaclave_types",
  "teaclave_worker",
  "thiserror",
+ "tokio",
  "url",
  "uuid",
 ]
@@ -1752,7 +1932,7 @@
  "teaclave_types",
  "thiserror",
  "tokio",
- "tokio-util",
+ "tokio-util 0.7.8",
  "url",
 ]
 
@@ -1777,6 +1957,7 @@
  "teaclave_test_utils",
  "teaclave_types",
  "thiserror",
+ "tokio",
 ]
 
 [[package]]
@@ -1810,6 +1991,7 @@
 version = "0.5.1"
 dependencies = [
  "anyhow",
+ "futures",
  "inventory",
  "lazy_static",
  "log",
@@ -1826,6 +2008,7 @@
  "teaclave_test_utils",
  "teaclave_types",
  "thiserror",
+ "tokio",
  "url",
  "uuid",
 ]
@@ -1837,22 +2020,16 @@
  "anyhow",
  "log",
  "rand",
- "rustls",
  "rusty-leveldb",
  "serde",
  "serde_json",
  "sgx_types",
- "teaclave_attestation",
  "teaclave_binder",
- "teaclave_config",
  "teaclave_crypto",
- "teaclave_proto",
- "teaclave_rpc",
  "teaclave_service_enclave_utils",
  "teaclave_test_utils",
  "teaclave_types",
  "teaclave_worker",
- "thiserror",
 ]
 
 [[package]]
@@ -1887,6 +2064,7 @@
  "teaclave_test_utils",
  "teaclave_types",
  "thiserror",
+ "tokio",
  "url",
  "uuid",
 ]
@@ -1896,17 +2074,15 @@
 version = "0.5.1"
 dependencies = [
  "anyhow",
- "base64 0.13.1",
- "cfg-if 0.1.10",
  "prost",
- "rand",
  "serde",
  "serde_json",
  "sgx_cov",
  "sgx_types",
  "teaclave_crypto",
- "teaclave_rpc",
  "teaclave_types",
+ "tonic",
+ "tonic-build",
  "url",
  "uuid",
 ]
@@ -1916,32 +2092,15 @@
 version = "0.5.1"
 dependencies = [
  "anyhow",
- "cfg-if 0.1.10",
- "http",
- "libc",
  "log",
  "rustls",
- "serde",
- "serde_json",
- "sgx_libc",
  "teaclave_attestation",
- "teaclave_rpc_proc_macro",
  "teaclave_types",
- "thiserror",
- "threadpool",
+ "tonic",
  "webpki",
 ]
 
 [[package]]
-name = "teaclave_rpc_proc_macro"
-version = "0.5.1"
-dependencies = [
- "proc-macro2 1.0.56",
- "quote 1.0.26",
- "syn 1.0.107",
-]
-
-[[package]]
 name = "teaclave_runtime"
 version = "0.5.1"
 dependencies = [
@@ -1973,6 +2132,7 @@
  "teaclave_test_utils",
  "teaclave_types",
  "thiserror",
+ "tokio",
  "uuid",
 ]
 
@@ -1990,17 +2150,8 @@
  "teaclave_logger",
  "teaclave_proto",
  "teaclave_rpc",
- "teaclave_service_enclave_utils_proc_macro",
  "teaclave_types",
-]
-
-[[package]]
-name = "teaclave_service_enclave_utils_proc_macro"
-version = "0.5.1"
-dependencies = [
- "proc-macro2 1.0.56",
- "quote 1.0.26",
- "syn 1.0.107",
+ "tokio",
 ]
 
 [[package]]
@@ -2039,14 +2190,17 @@
  "teaclave_test_utils",
  "teaclave_types",
  "thiserror",
+ "tokio",
 ]
 
 [[package]]
 name = "teaclave_test_utils"
 version = "0.5.1"
 dependencies = [
+ "futures",
  "inventory",
  "teaclave_test_utils_proc_macro",
+ "tokio",
 ]
 
 [[package]]
@@ -2054,8 +2208,8 @@
 version = "0.0.1"
 dependencies = [
  "proc-macro2 1.0.56",
- "quote 1.0.26",
- "syn 1.0.107",
+ "quote 1.0.27",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -2075,6 +2229,7 @@
  "teaclave_test_utils",
  "thiserror",
  "toml",
+ "tonic",
  "url",
  "uuid",
 ]
@@ -2130,44 +2285,35 @@
 
 [[package]]
 name = "tempfile"
-version = "3.4.0"
+version = "3.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af18f7ae1acd354b992402e9ec5864359d693cd8a79dcbef59f76891701c1e95"
+checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998"
 dependencies = [
  "cfg-if 1.0.0",
  "fastrand",
  "redox_syscall",
  "rustix",
- "windows-sys 0.42.0",
+ "windows-sys 0.45.0",
 ]
 
 [[package]]
 name = "thiserror"
-version = "1.0.38"
+version = "1.0.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0"
+checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
 dependencies = [
  "thiserror-impl",
 ]
 
 [[package]]
 name = "thiserror-impl"
-version = "1.0.38"
+version = "1.0.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
+checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
 dependencies = [
  "proc-macro2 1.0.56",
- "quote 1.0.26",
- "syn 1.0.107",
-]
-
-[[package]]
-name = "threadpool"
-version = "1.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa"
-dependencies = [
- "num_cpus",
+ "quote 1.0.27",
+ "syn 2.0.15",
 ]
 
 [[package]]
@@ -2181,24 +2327,45 @@
 
 [[package]]
 name = "tinyvec_macros"
-version = "0.1.0"
+version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
+checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
 
 [[package]]
 name = "tokio"
-version = "1.27.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d0de47a4eecbe11f498978a9b29d792f0d2692d1dd003650c24c76510e3bc001"
+version = "1.24.0"
+source = "git+https://github.com/tokio-rs/tokio.git?tag=tokio-1.24.0#dfe252d1fa82bdfefd7cba20f9a88cdd27e310cc"
 dependencies = [
  "autocfg",
  "bytes",
  "libc",
+ "memchr",
  "mio",
  "num_cpus",
  "pin-project-lite",
  "socket2",
- "windows-sys 0.45.0",
+ "tokio-macros",
+ "windows-sys 0.42.0",
+]
+
+[[package]]
+name = "tokio-io-timeout"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf"
+dependencies = [
+ "pin-project-lite",
+ "tokio",
+]
+
+[[package]]
+name = "tokio-macros"
+version = "1.8.2"
+source = "git+https://github.com/tokio-rs/tokio.git?tag=tokio-1.24.0#dfe252d1fa82bdfefd7cba20f9a88cdd27e310cc"
+dependencies = [
+ "proc-macro2 1.0.56",
+ "quote 1.0.27",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -2212,10 +2379,46 @@
 ]
 
 [[package]]
-name = "tokio-util"
-version = "0.7.7"
+name = "tokio-rustls"
+version = "0.22.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2"
+checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6"
+dependencies = [
+ "rustls",
+ "tokio",
+ "webpki",
+]
+
+[[package]]
+name = "tokio-stream"
+version = "0.1.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842"
+dependencies = [
+ "futures-core",
+ "pin-project-lite",
+ "tokio",
+]
+
+[[package]]
+name = "tokio-util"
+version = "0.6.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507"
+dependencies = [
+ "bytes",
+ "futures-core",
+ "futures-sink",
+ "log",
+ "pin-project-lite",
+ "tokio",
+]
+
+[[package]]
+name = "tokio-util"
+version = "0.7.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d"
 dependencies = [
  "bytes",
  "futures-core",
@@ -2227,14 +2430,85 @@
 
 [[package]]
 name = "toml"
-version = "0.5.10"
+version = "0.5.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1333c76748e868a4d9d1017b5ab53171dfd095f70c712fdb4653a406547f598f"
+checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234"
 dependencies = [
  "serde",
 ]
 
 [[package]]
+name = "tonic"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ff08f4649d10a70ffa3522ca559031285d8e421d727ac85c60825761818f5d0a"
+dependencies = [
+ "async-stream",
+ "async-trait",
+ "base64 0.13.1",
+ "bytes",
+ "flate2",
+ "futures-core",
+ "futures-util",
+ "h2",
+ "http",
+ "http-body",
+ "hyper",
+ "hyper-timeout",
+ "percent-encoding",
+ "pin-project",
+ "prost",
+ "prost-derive",
+ "tokio",
+ "tokio-rustls",
+ "tokio-stream",
+ "tokio-util 0.6.10",
+ "tower",
+ "tower-layer",
+ "tower-service",
+ "tracing",
+ "tracing-futures",
+]
+
+[[package]]
+name = "tonic-build"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9403f1bafde247186684b230dc6f38b5cd514584e8bec1dd32514be4745fa757"
+dependencies = [
+ "proc-macro2 1.0.56",
+ "prost-build",
+ "quote 1.0.27",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "tower"
+version = "0.4.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
+dependencies = [
+ "futures-core",
+ "futures-util",
+ "indexmap",
+ "pin-project",
+ "pin-project-lite",
+ "rand",
+ "slab",
+ "tokio",
+ "tokio-util 0.7.8",
+ "tower-layer",
+ "tower-service",
+ "tracing",
+]
+
+[[package]]
+name = "tower-layer"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0"
+
+[[package]]
 name = "tower-service"
 version = "0.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2247,11 +2521,24 @@
 checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
 dependencies = [
  "cfg-if 1.0.0",
+ "log",
  "pin-project-lite",
+ "tracing-attributes",
  "tracing-core",
 ]
 
 [[package]]
+name = "tracing-attributes"
+version = "0.1.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74"
+dependencies = [
+ "proc-macro2 1.0.56",
+ "quote 1.0.27",
+ "syn 2.0.15",
+]
+
+[[package]]
 name = "tracing-core"
 version = "0.1.30"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2261,6 +2548,16 @@
 ]
 
 [[package]]
+name = "tracing-futures"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2"
+dependencies = [
+ "pin-project",
+ "tracing",
+]
+
+[[package]]
 name = "try-lock"
 version = "0.2.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2268,15 +2565,15 @@
 
 [[package]]
 name = "unicode-bidi"
-version = "0.3.8"
+version = "0.3.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992"
+checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460"
 
 [[package]]
 name = "unicode-ident"
-version = "1.0.6"
+version = "1.0.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
+checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
 
 [[package]]
 name = "unicode-normalization"
@@ -2288,6 +2585,12 @@
 ]
 
 [[package]]
+name = "unicode-segmentation"
+version = "1.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36"
+
+[[package]]
 name = "unicode-xid"
 version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2369,9 +2672,9 @@
 
 [[package]]
 name = "wasm-bindgen"
-version = "0.2.83"
+version = "0.2.85"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268"
+checksum = "5b6cb788c4e39112fbe1822277ef6fb3c55cd86b95cb3d3c4c1c9597e4ac74b4"
 dependencies = [
  "cfg-if 1.0.0",
  "wasm-bindgen-macro",
@@ -2379,24 +2682,24 @@
 
 [[package]]
 name = "wasm-bindgen-backend"
-version = "0.2.83"
+version = "0.2.85"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142"
+checksum = "35e522ed4105a9d626d885b35d62501b30d9666283a5c8be12c14a8bdafe7822"
 dependencies = [
  "bumpalo",
  "log",
  "once_cell",
  "proc-macro2 1.0.56",
- "quote 1.0.26",
- "syn 1.0.107",
+ "quote 1.0.27",
+ "syn 2.0.15",
  "wasm-bindgen-shared",
 ]
 
 [[package]]
 name = "wasm-bindgen-futures"
-version = "0.4.33"
+version = "0.4.35"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d"
+checksum = "083abe15c5d88556b77bdf7aef403625be9e327ad37c62c4e4129af740168163"
 dependencies = [
  "cfg-if 1.0.0",
  "js-sys",
@@ -2406,32 +2709,32 @@
 
 [[package]]
 name = "wasm-bindgen-macro"
-version = "0.2.83"
+version = "0.2.85"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810"
+checksum = "358a79a0cb89d21db8120cbfb91392335913e4890665b1a7981d9e956903b434"
 dependencies = [
- "quote 1.0.26",
+ "quote 1.0.27",
  "wasm-bindgen-macro-support",
 ]
 
 [[package]]
 name = "wasm-bindgen-macro-support"
-version = "0.2.83"
+version = "0.2.85"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
+checksum = "4783ce29f09b9d93134d41297aded3a712b7b979e9c6f28c32cb88c973a94869"
 dependencies = [
  "proc-macro2 1.0.56",
- "quote 1.0.26",
- "syn 1.0.107",
+ "quote 1.0.27",
+ "syn 2.0.15",
  "wasm-bindgen-backend",
  "wasm-bindgen-shared",
 ]
 
 [[package]]
 name = "wasm-bindgen-shared"
-version = "0.2.83"
+version = "0.2.85"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f"
+checksum = "a901d592cafaa4d711bc324edfaff879ac700b19c3dfd60058d2b445be2691eb"
 
 [[package]]
 name = "wasm-streams"
@@ -2448,9 +2751,9 @@
 
 [[package]]
 name = "web-sys"
-version = "0.3.60"
+version = "0.3.62"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f"
+checksum = "16b5f940c7edfdc6d12126d98c9ef4d1b3d470011c47c76a6581df47ad9ba721"
 dependencies = [
  "js-sys",
  "wasm-bindgen",
@@ -2476,6 +2779,17 @@
 ]
 
 [[package]]
+name = "which"
+version = "4.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269"
+dependencies = [
+ "either",
+ "libc",
+ "once_cell",
+]
+
+[[package]]
 name = "winapi"
 version = "0.3.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2503,13 +2817,13 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
 dependencies = [
- "windows_aarch64_gnullvm 0.42.1",
- "windows_aarch64_msvc 0.42.1",
- "windows_i686_gnu 0.42.1",
- "windows_i686_msvc 0.42.1",
- "windows_x86_64_gnu 0.42.1",
- "windows_x86_64_gnullvm 0.42.1",
- "windows_x86_64_msvc 0.42.1",
+ "windows_aarch64_gnullvm 0.42.2",
+ "windows_aarch64_msvc 0.42.2",
+ "windows_i686_gnu 0.42.2",
+ "windows_i686_msvc 0.42.2",
+ "windows_x86_64_gnu 0.42.2",
+ "windows_x86_64_gnullvm 0.42.2",
+ "windows_x86_64_msvc 0.42.2",
 ]
 
 [[package]]
@@ -2518,7 +2832,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
 dependencies = [
- "windows-targets 0.42.1",
+ "windows-targets 0.42.2",
 ]
 
 [[package]]
@@ -2532,17 +2846,17 @@
 
 [[package]]
 name = "windows-targets"
-version = "0.42.1"
+version = "0.42.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7"
+checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
 dependencies = [
- "windows_aarch64_gnullvm 0.42.1",
- "windows_aarch64_msvc 0.42.1",
- "windows_i686_gnu 0.42.1",
- "windows_i686_msvc 0.42.1",
- "windows_x86_64_gnu 0.42.1",
- "windows_x86_64_gnullvm 0.42.1",
- "windows_x86_64_msvc 0.42.1",
+ "windows_aarch64_gnullvm 0.42.2",
+ "windows_aarch64_msvc 0.42.2",
+ "windows_i686_gnu 0.42.2",
+ "windows_i686_msvc 0.42.2",
+ "windows_x86_64_gnu 0.42.2",
+ "windows_x86_64_gnullvm 0.42.2",
+ "windows_x86_64_msvc 0.42.2",
 ]
 
 [[package]]
@@ -2562,9 +2876,9 @@
 
 [[package]]
 name = "windows_aarch64_gnullvm"
-version = "0.42.1"
+version = "0.42.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608"
+checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
 
 [[package]]
 name = "windows_aarch64_gnullvm"
@@ -2574,9 +2888,9 @@
 
 [[package]]
 name = "windows_aarch64_msvc"
-version = "0.42.1"
+version = "0.42.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7"
+checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
 
 [[package]]
 name = "windows_aarch64_msvc"
@@ -2586,9 +2900,9 @@
 
 [[package]]
 name = "windows_i686_gnu"
-version = "0.42.1"
+version = "0.42.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640"
+checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
 
 [[package]]
 name = "windows_i686_gnu"
@@ -2598,9 +2912,9 @@
 
 [[package]]
 name = "windows_i686_msvc"
-version = "0.42.1"
+version = "0.42.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605"
+checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
 
 [[package]]
 name = "windows_i686_msvc"
@@ -2610,9 +2924,9 @@
 
 [[package]]
 name = "windows_x86_64_gnu"
-version = "0.42.1"
+version = "0.42.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45"
+checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
 
 [[package]]
 name = "windows_x86_64_gnu"
@@ -2622,9 +2936,9 @@
 
 [[package]]
 name = "windows_x86_64_gnullvm"
-version = "0.42.1"
+version = "0.42.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463"
+checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
 
 [[package]]
 name = "windows_x86_64_gnullvm"
@@ -2634,9 +2948,9 @@
 
 [[package]]
 name = "windows_x86_64_msvc"
-version = "0.42.1"
+version = "0.42.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"
+checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
 
 [[package]]
 name = "windows_x86_64_msvc"
diff --git a/cmake/tomls/Cargo.sgx_trusted_lib.toml b/cmake/tomls/Cargo.sgx_trusted_lib.toml
index 333f7c6..4bacf77 100644
--- a/cmake/tomls/Cargo.sgx_trusted_lib.toml
+++ b/cmake/tomls/Cargo.sgx_trusted_lib.toml
@@ -65,4 +65,5 @@
 rustface          = { git = "https://github.com/apache/incubator-teaclave-crates" }
 rustls            = { git = "https://github.com/apache/incubator-teaclave-crates" }
 rusty-machine     = { git = "https://github.com/apache/incubator-teaclave-crates" }
+tokio             = { git = "https://github.com/tokio-rs/tokio.git", tag = "tokio-1.24.0"}
 yasna             = { git = "https://github.com/sccommunity/yasna.rs", branch = "teaclave-sgx" }
diff --git a/cmake/tomls/Cargo.sgx_untrusted_app.lock b/cmake/tomls/Cargo.sgx_untrusted_app.lock
index 3088002..16b0b01 100644
--- a/cmake/tomls/Cargo.sgx_untrusted_app.lock
+++ b/cmake/tomls/Cargo.sgx_untrusted_app.lock
@@ -3,6 +3,12 @@
 version = 3
 
 [[package]]
+name = "adler"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
+
+[[package]]
 name = "aho-corasick"
 version = "0.7.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -27,6 +33,39 @@
 checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61"
 
 [[package]]
+name = "async-stream"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51"
+dependencies = [
+ "async-stream-impl",
+ "futures-core",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "async-stream-impl"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193"
+dependencies = [
+ "proc-macro2 1.0.56",
+ "quote 1.0.26",
+ "syn 2.0.15",
+]
+
+[[package]]
+name = "async-trait"
+version = "0.1.68"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842"
+dependencies = [
+ "proc-macro2 1.0.56",
+ "quote 1.0.26",
+ "syn 2.0.15",
+]
+
+[[package]]
 name = "atty"
 version = "0.2.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -175,6 +214,15 @@
 checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
 
 [[package]]
+name = "crc32fast"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
+dependencies = [
+ "cfg-if 1.0.0",
+]
+
+[[package]]
 name = "ctor"
 version = "0.1.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -241,6 +289,22 @@
 ]
 
 [[package]]
+name = "fixedbitset"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
+
+[[package]]
+name = "flate2"
+version = "1.0.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743"
+dependencies = [
+ "crc32fast",
+ "miniz_oxide",
+]
+
+[[package]]
 name = "fnv"
 version = "1.0.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -416,7 +480,7 @@
  "indexmap",
  "slab",
  "tokio",
- "tokio-util",
+ "tokio-util 0.7.7",
  "tracing",
 ]
 
@@ -531,6 +595,18 @@
 ]
 
 [[package]]
+name = "hyper-timeout"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1"
+dependencies = [
+ "hyper",
+ "pin-project-lite",
+ "tokio",
+ "tokio-io-timeout",
+]
+
+[[package]]
 name = "hyper-tls"
 version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -704,6 +780,15 @@
 checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
 
 [[package]]
+name = "miniz_oxide"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
+dependencies = [
+ "adler",
+]
+
+[[package]]
 name = "mio"
 version = "0.8.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -716,6 +801,12 @@
 ]
 
 [[package]]
+name = "multimap"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a"
+
+[[package]]
 name = "native-tls"
 version = "0.2.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -912,6 +1003,36 @@
 checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
 
 [[package]]
+name = "petgraph"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4"
+dependencies = [
+ "fixedbitset",
+ "indexmap",
+]
+
+[[package]]
+name = "pin-project"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc"
+dependencies = [
+ "pin-project-internal",
+]
+
+[[package]]
+name = "pin-project-internal"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55"
+dependencies = [
+ "proc-macro2 1.0.56",
+ "quote 1.0.26",
+ "syn 1.0.107",
+]
+
+[[package]]
 name = "pin-project-lite"
 version = "0.2.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -979,19 +1100,39 @@
 
 [[package]]
 name = "prost"
-version = "0.11.8"
+version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e48e50df39172a3e7eb17e14642445da64996989bc212b583015435d39a58537"
+checksum = "444879275cb4fd84958b1a1d5420d15e6fcf7c235fe47f053c9c2a80aceb6001"
 dependencies = [
  "bytes",
  "prost-derive",
 ]
 
 [[package]]
-name = "prost-derive"
-version = "0.11.8"
+name = "prost-build"
+version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ea9b0f8cbe5e15a8a042d030bd96668db28ecb567ec37d691971ff5731d2b1b"
+checksum = "62941722fb675d463659e49c4f3fe1fe792ff24fe5bbaa9c08cd3b98a1c354f5"
+dependencies = [
+ "bytes",
+ "heck",
+ "itertools 0.10.5",
+ "lazy_static",
+ "log",
+ "multimap",
+ "petgraph",
+ "prost",
+ "prost-types",
+ "regex",
+ "tempfile",
+ "which",
+]
+
+[[package]]
+name = "prost-derive"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f9cc1a3263e07e0bf68e96268f37665207b49560d98739662cdfaae215c720fe"
 dependencies = [
  "anyhow",
  "itertools 0.10.5",
@@ -1001,6 +1142,16 @@
 ]
 
 [[package]]
+name = "prost-types"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "534b7a0e836e3c482d2693070f982e39e7611da9695d4d1f5a4b186b51faef0a"
+dependencies = [
+ "bytes",
+ "prost",
+]
+
+[[package]]
 name = "quick-error"
 version = "1.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1267,7 +1418,7 @@
  "serde_urlencoded",
  "tokio",
  "tokio-native-tls",
- "tokio-util",
+ "tokio-util 0.7.7",
  "tower-service",
  "url",
  "wasm-bindgen",
@@ -1482,18 +1633,6 @@
 ]
 
 [[package]]
-name = "sgx_libc"
-version = "2.0.0"
-dependencies = [
- "sgx_ffi",
- "sgx_oc",
- "sgx_sync",
- "sgx_tlibc_sys",
- "sgx_trts",
- "sgx_types",
-]
-
-[[package]]
 name = "sgx_macros"
 version = "2.0.0"
 dependencies = [
@@ -1747,6 +1886,17 @@
 ]
 
 [[package]]
+name = "syn"
+version = "2.0.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822"
+dependencies = [
+ "proc-macro2 1.0.56",
+ "quote 1.0.26",
+ "unicode-ident",
+]
+
+[[package]]
 name = "teaclave_access_control_service"
 version = "0.5.1"
 dependencies = [
@@ -1866,6 +2016,7 @@
  "teaclave_file_agent",
  "teaclave_logger",
  "teaclave_service_app_utils",
+ "tokio",
 ]
 
 [[package]]
@@ -1891,6 +2042,7 @@
  "teaclave_types",
  "teaclave_worker",
  "thiserror",
+ "tokio",
  "url",
  "uuid",
 ]
@@ -1955,7 +2107,7 @@
  "teaclave_types",
  "thiserror",
  "tokio",
- "tokio-util",
+ "tokio-util 0.7.7",
  "url",
 ]
 
@@ -2050,17 +2202,15 @@
 version = "0.5.1"
 dependencies = [
  "anyhow",
- "base64 0.13.1",
- "cfg-if 0.1.10",
  "prost",
- "rand 0.8.5",
  "serde",
  "serde_json",
  "sgx_cov",
  "sgx_types",
  "teaclave_crypto",
- "teaclave_rpc",
  "teaclave_types",
+ "tonic",
+ "tonic-build",
  "url",
  "uuid",
 ]
@@ -2070,32 +2220,15 @@
 version = "0.5.1"
 dependencies = [
  "anyhow",
- "cfg-if 0.1.10",
- "http",
- "libc",
  "log",
  "rustls",
- "serde",
- "serde_json",
- "sgx_libc",
  "teaclave_attestation",
- "teaclave_rpc_proc_macro",
  "teaclave_types",
- "thiserror",
- "threadpool",
+ "tonic",
  "webpki",
 ]
 
 [[package]]
-name = "teaclave_rpc_proc_macro"
-version = "0.5.1"
-dependencies = [
- "proc-macro2 1.0.56",
- "quote 1.0.26",
- "syn 1.0.107",
-]
-
-[[package]]
 name = "teaclave_runtime"
 version = "0.5.1"
 dependencies = [
@@ -2147,17 +2280,8 @@
  "teaclave_logger",
  "teaclave_proto",
  "teaclave_rpc",
- "teaclave_service_enclave_utils_proc_macro",
  "teaclave_types",
-]
-
-[[package]]
-name = "teaclave_service_enclave_utils_proc_macro"
-version = "0.5.1"
-dependencies = [
- "proc-macro2 1.0.56",
- "quote 1.0.26",
- "syn 1.0.107",
+ "tokio",
 ]
 
 [[package]]
@@ -2191,8 +2315,10 @@
 name = "teaclave_test_utils"
 version = "0.5.1"
 dependencies = [
+ "futures",
  "inventory",
  "teaclave_test_utils_proc_macro",
+ "tokio",
 ]
 
 [[package]]
@@ -2221,6 +2347,7 @@
  "teaclave_test_utils",
  "thiserror",
  "toml",
+ "tonic",
  "url",
  "uuid",
 ]
@@ -2308,15 +2435,6 @@
 ]
 
 [[package]]
-name = "threadpool"
-version = "1.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa"
-dependencies = [
- "num_cpus",
-]
-
-[[package]]
 name = "tinyvec"
 version = "1.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2344,10 +2462,32 @@
  "num_cpus",
  "pin-project-lite",
  "socket2",
+ "tokio-macros",
  "windows-sys 0.45.0",
 ]
 
 [[package]]
+name = "tokio-io-timeout"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf"
+dependencies = [
+ "pin-project-lite",
+ "tokio",
+]
+
+[[package]]
+name = "tokio-macros"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "61a573bdc87985e9d6ddeed1b3d864e8a302c847e40d647746df2f1de209d1ce"
+dependencies = [
+ "proc-macro2 1.0.56",
+ "quote 1.0.26",
+ "syn 2.0.15",
+]
+
+[[package]]
 name = "tokio-native-tls"
 version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2358,6 +2498,42 @@
 ]
 
 [[package]]
+name = "tokio-rustls"
+version = "0.22.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6"
+dependencies = [
+ "rustls",
+ "tokio",
+ "webpki",
+]
+
+[[package]]
+name = "tokio-stream"
+version = "0.1.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842"
+dependencies = [
+ "futures-core",
+ "pin-project-lite",
+ "tokio",
+]
+
+[[package]]
+name = "tokio-util"
+version = "0.6.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507"
+dependencies = [
+ "bytes",
+ "futures-core",
+ "futures-sink",
+ "log",
+ "pin-project-lite",
+ "tokio",
+]
+
+[[package]]
 name = "tokio-util"
 version = "0.7.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2381,6 +2557,77 @@
 ]
 
 [[package]]
+name = "tonic"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ff08f4649d10a70ffa3522ca559031285d8e421d727ac85c60825761818f5d0a"
+dependencies = [
+ "async-stream",
+ "async-trait",
+ "base64 0.13.1",
+ "bytes",
+ "flate2",
+ "futures-core",
+ "futures-util",
+ "h2",
+ "http",
+ "http-body",
+ "hyper",
+ "hyper-timeout",
+ "percent-encoding",
+ "pin-project",
+ "prost",
+ "prost-derive",
+ "tokio",
+ "tokio-rustls",
+ "tokio-stream",
+ "tokio-util 0.6.10",
+ "tower",
+ "tower-layer",
+ "tower-service",
+ "tracing",
+ "tracing-futures",
+]
+
+[[package]]
+name = "tonic-build"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9403f1bafde247186684b230dc6f38b5cd514584e8bec1dd32514be4745fa757"
+dependencies = [
+ "proc-macro2 1.0.56",
+ "prost-build",
+ "quote 1.0.26",
+ "syn 1.0.107",
+]
+
+[[package]]
+name = "tower"
+version = "0.4.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
+dependencies = [
+ "futures-core",
+ "futures-util",
+ "indexmap",
+ "pin-project",
+ "pin-project-lite",
+ "rand 0.8.5",
+ "slab",
+ "tokio",
+ "tokio-util 0.7.7",
+ "tower-layer",
+ "tower-service",
+ "tracing",
+]
+
+[[package]]
+name = "tower-layer"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0"
+
+[[package]]
 name = "tower-service"
 version = "0.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2393,11 +2640,24 @@
 checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
 dependencies = [
  "cfg-if 1.0.0",
+ "log",
  "pin-project-lite",
+ "tracing-attributes",
  "tracing-core",
 ]
 
 [[package]]
+name = "tracing-attributes"
+version = "0.1.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74"
+dependencies = [
+ "proc-macro2 1.0.56",
+ "quote 1.0.26",
+ "syn 2.0.15",
+]
+
+[[package]]
 name = "tracing-core"
 version = "0.1.30"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2407,6 +2667,16 @@
 ]
 
 [[package]]
+name = "tracing-futures"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2"
+dependencies = [
+ "pin-project",
+ "tracing",
+]
+
+[[package]]
 name = "try-lock"
 version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2634,6 +2904,17 @@
 ]
 
 [[package]]
+name = "which"
+version = "4.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269"
+dependencies = [
+ "either",
+ "libc",
+ "once_cell",
+]
+
+[[package]]
 name = "winapi"
 version = "0.3.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/cmake/tomls/Cargo.sgx_untrusted_app.toml b/cmake/tomls/Cargo.sgx_untrusted_app.toml
index f41e982..c83473d 100644
--- a/cmake/tomls/Cargo.sgx_untrusted_app.toml
+++ b/cmake/tomls/Cargo.sgx_untrusted_app.toml
@@ -39,7 +39,6 @@
 # We cannot remove these crates, because proto crates depend on them
 sgx_crypto        = { path = "../../../third_party/rust-sgx-sdk/sgx_crypto" }
 sgx_cov           = { path = "../../../third_party/rust-sgx-sdk/sgx_tests/cov" }
-sgx_libc          = { path = "../../../third_party/rust-sgx-sdk/sgx_libc" }
 sgx_macros        = { path = "../../../third_party/rust-sgx-sdk/sgx_macros" }
 sgx_rand          = { path = "../../../third_party/rust-sgx-sdk/sgx_rand" }
 sgx_tprotected_fs = { path = "../../../third_party/rust-sgx-sdk/sgx_protected_fs/tfs" }
diff --git a/cmake/tomls/Cargo.unix_app.lock b/cmake/tomls/Cargo.unix_app.lock
index 389a644..f7050aa 100644
--- a/cmake/tomls/Cargo.unix_app.lock
+++ b/cmake/tomls/Cargo.unix_app.lock
@@ -3,6 +3,12 @@
 version = 3
 
 [[package]]
+name = "adler"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
+
+[[package]]
 name = "aead"
 version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -287,6 +293,15 @@
 ]
 
 [[package]]
+name = "crc32fast"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
+dependencies = [
+ "cfg-if 1.0.0",
+]
+
+[[package]]
 name = "crypto-common"
 version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -456,6 +471,22 @@
 ]
 
 [[package]]
+name = "fixedbitset"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
+
+[[package]]
+name = "flate2"
+version = "1.0.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743"
+dependencies = [
+ "crc32fast",
+ "miniz_oxide",
+]
+
+[[package]]
 name = "fnv"
 version = "1.0.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -478,6 +509,7 @@
 dependencies = [
  "futures-channel",
  "futures-core",
+ "futures-executor",
  "futures-io",
  "futures-sink",
  "futures-task",
@@ -501,12 +533,34 @@
 checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac"
 
 [[package]]
+name = "futures-executor"
+version = "0.3.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7acc85df6714c176ab5edf386123fafe217be88c0840ec11f199441134a074e2"
+dependencies = [
+ "futures-core",
+ "futures-task",
+ "futures-util",
+]
+
+[[package]]
 name = "futures-io"
 version = "0.3.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb"
 
 [[package]]
+name = "futures-macro"
+version = "0.3.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
 name = "futures-sink"
 version = "0.3.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -527,6 +581,7 @@
  "futures-channel",
  "futures-core",
  "futures-io",
+ "futures-macro",
  "futures-sink",
  "futures-task",
  "memchr",
@@ -611,7 +666,7 @@
  "indexmap",
  "slab",
  "tokio",
- "tokio-util",
+ "tokio-util 0.7.4",
  "tracing",
 ]
 
@@ -744,6 +799,18 @@
 ]
 
 [[package]]
+name = "hyper-timeout"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1"
+dependencies = [
+ "hyper",
+ "pin-project-lite",
+ "tokio",
+ "tokio-io-timeout",
+]
+
+[[package]]
 name = "iana-time-zone"
 version = "0.1.53"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -935,6 +1002,15 @@
 checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
 
 [[package]]
+name = "miniz_oxide"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
+dependencies = [
+ "adler",
+]
+
+[[package]]
 name = "mio"
 version = "0.8.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -962,11 +1038,17 @@
  "mime",
  "spin 0.9.4",
  "tokio",
- "tokio-util",
+ "tokio-util 0.7.4",
  "version_check",
 ]
 
 [[package]]
+name = "multimap"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a"
+
+[[package]]
 name = "nu-ansi-term"
 version = "0.46.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1098,6 +1180,36 @@
 checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
 
 [[package]]
+name = "petgraph"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4"
+dependencies = [
+ "fixedbitset",
+ "indexmap",
+]
+
+[[package]]
+name = "pin-project"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc"
+dependencies = [
+ "pin-project-internal",
+]
+
+[[package]]
+name = "pin-project-internal"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
 name = "pin-project-lite"
 version = "0.2.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1175,19 +1287,39 @@
 
 [[package]]
 name = "prost"
-version = "0.11.8"
+version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e48e50df39172a3e7eb17e14642445da64996989bc212b583015435d39a58537"
+checksum = "444879275cb4fd84958b1a1d5420d15e6fcf7c235fe47f053c9c2a80aceb6001"
 dependencies = [
  "bytes",
  "prost-derive",
 ]
 
 [[package]]
-name = "prost-derive"
-version = "0.11.8"
+name = "prost-build"
+version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ea9b0f8cbe5e15a8a042d030bd96668db28ecb567ec37d691971ff5731d2b1b"
+checksum = "62941722fb675d463659e49c4f3fe1fe792ff24fe5bbaa9c08cd3b98a1c354f5"
+dependencies = [
+ "bytes",
+ "heck",
+ "itertools",
+ "lazy_static",
+ "log",
+ "multimap",
+ "petgraph",
+ "prost",
+ "prost-types",
+ "regex",
+ "tempfile",
+ "which",
+]
+
+[[package]]
+name = "prost-derive"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f9cc1a3263e07e0bf68e96268f37665207b49560d98739662cdfaae215c720fe"
 dependencies = [
  "anyhow",
  "itertools",
@@ -1197,6 +1329,16 @@
 ]
 
 [[package]]
+name = "prost-types"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "534b7a0e836e3c482d2693070f982e39e7611da9695d4d1f5a4b186b51faef0a"
+dependencies = [
+ "bytes",
+ "prost",
+]
+
+[[package]]
 name = "quick-error"
 version = "1.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1360,7 +1502,7 @@
  "time 0.3.17",
  "tokio",
  "tokio-stream",
- "tokio-util",
+ "tokio-util 0.7.4",
  "ubyte",
  "version_check",
  "yansi",
@@ -1406,7 +1548,7 @@
  "state",
  "time 0.3.17",
  "tokio",
- "tokio-rustls",
+ "tokio-rustls 0.23.4",
  "uncased",
 ]
 
@@ -1576,18 +1718,6 @@
 ]
 
 [[package]]
-name = "sgx_libc"
-version = "2.0.0"
-dependencies = [
- "sgx_ffi",
- "sgx_oc",
- "sgx_sync",
- "sgx_tlibc_sys",
- "sgx_trts",
- "sgx_types",
-]
-
-[[package]]
 name = "sgx_oc"
 version = "2.0.0"
 dependencies = [
@@ -1909,6 +2039,7 @@
  "teaclave_proto",
  "teaclave_rpc",
  "teaclave_types",
+ "tokio",
  "url",
 ]
 
@@ -1964,17 +2095,15 @@
 version = "0.5.1"
 dependencies = [
  "anyhow",
- "base64 0.13.1",
- "cfg-if 0.1.10",
  "prost",
- "rand",
  "serde",
  "serde_json",
  "sgx_cov",
  "sgx_types",
  "teaclave_crypto",
- "teaclave_rpc",
  "teaclave_types",
+ "tonic",
+ "tonic-build",
  "url",
  "uuid",
 ]
@@ -1984,37 +2113,22 @@
 version = "0.5.1"
 dependencies = [
  "anyhow",
- "cfg-if 0.1.10",
- "http",
- "libc",
  "log",
  "rustls 0.19.1",
- "serde",
- "serde_json",
- "sgx_libc",
  "teaclave_attestation",
- "teaclave_rpc_proc_macro",
  "teaclave_types",
- "thiserror",
- "threadpool",
+ "tonic",
  "webpki 0.21.4",
 ]
 
 [[package]]
-name = "teaclave_rpc_proc_macro"
-version = "0.5.1"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
 name = "teaclave_test_utils"
 version = "0.5.1"
 dependencies = [
+ "futures",
  "inventory",
  "teaclave_test_utils_proc_macro",
+ "tokio",
 ]
 
 [[package]]
@@ -2043,6 +2157,7 @@
  "teaclave_test_utils",
  "thiserror",
  "toml",
+ "tonic",
  "url",
  "uuid",
 ]
@@ -2109,15 +2224,6 @@
 ]
 
 [[package]]
-name = "threadpool"
-version = "1.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa"
-dependencies = [
- "num_cpus",
-]
-
-[[package]]
 name = "time"
 version = "0.1.45"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2190,6 +2296,16 @@
 ]
 
 [[package]]
+name = "tokio-io-timeout"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf"
+dependencies = [
+ "pin-project-lite",
+ "tokio",
+]
+
+[[package]]
 name = "tokio-macros"
 version = "1.8.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2202,6 +2318,17 @@
 
 [[package]]
 name = "tokio-rustls"
+version = "0.22.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6"
+dependencies = [
+ "rustls 0.19.1",
+ "tokio",
+ "webpki 0.21.4",
+]
+
+[[package]]
+name = "tokio-rustls"
 version = "0.23.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59"
@@ -2224,6 +2351,20 @@
 
 [[package]]
 name = "tokio-util"
+version = "0.6.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507"
+dependencies = [
+ "bytes",
+ "futures-core",
+ "futures-sink",
+ "log",
+ "pin-project-lite",
+ "tokio",
+]
+
+[[package]]
+name = "tokio-util"
 version = "0.7.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740"
@@ -2246,6 +2387,77 @@
 ]
 
 [[package]]
+name = "tonic"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ff08f4649d10a70ffa3522ca559031285d8e421d727ac85c60825761818f5d0a"
+dependencies = [
+ "async-stream",
+ "async-trait",
+ "base64 0.13.1",
+ "bytes",
+ "flate2",
+ "futures-core",
+ "futures-util",
+ "h2",
+ "http",
+ "http-body",
+ "hyper",
+ "hyper-timeout",
+ "percent-encoding",
+ "pin-project",
+ "prost",
+ "prost-derive",
+ "tokio",
+ "tokio-rustls 0.22.0",
+ "tokio-stream",
+ "tokio-util 0.6.10",
+ "tower",
+ "tower-layer",
+ "tower-service",
+ "tracing",
+ "tracing-futures",
+]
+
+[[package]]
+name = "tonic-build"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9403f1bafde247186684b230dc6f38b5cd514584e8bec1dd32514be4745fa757"
+dependencies = [
+ "proc-macro2",
+ "prost-build",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "tower"
+version = "0.4.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
+dependencies = [
+ "futures-core",
+ "futures-util",
+ "indexmap",
+ "pin-project",
+ "pin-project-lite",
+ "rand",
+ "slab",
+ "tokio",
+ "tokio-util 0.7.4",
+ "tower-layer",
+ "tower-service",
+ "tracing",
+]
+
+[[package]]
+name = "tower-layer"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0"
+
+[[package]]
 name = "tower-service"
 version = "0.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2258,6 +2470,7 @@
 checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
 dependencies = [
  "cfg-if 1.0.0",
+ "log",
  "pin-project-lite",
  "tracing-attributes",
  "tracing-core",
@@ -2285,6 +2498,16 @@
 ]
 
 [[package]]
+name = "tracing-futures"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2"
+dependencies = [
+ "pin-project",
+ "tracing",
+]
+
+[[package]]
 name = "tracing-log"
 version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2556,6 +2779,17 @@
 ]
 
 [[package]]
+name = "which"
+version = "4.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269"
+dependencies = [
+ "either",
+ "libc",
+ "once_cell",
+]
+
+[[package]]
 name = "winapi"
 version = "0.3.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/cmake/tomls/Cargo.unix_app.toml b/cmake/tomls/Cargo.unix_app.toml
index a2a9efd..c9cc713 100644
--- a/cmake/tomls/Cargo.unix_app.toml
+++ b/cmake/tomls/Cargo.unix_app.toml
@@ -33,7 +33,6 @@
 
 sgx_cov           = { path = "../../../third_party/rust-sgx-sdk/sgx_tests/cov" }
 sgx_crypto        = { path = "../../../third_party/rust-sgx-sdk/sgx_crypto" }
-sgx_libc          = { path = "../../../third_party/rust-sgx-sdk/sgx_libc" }
 sgx_rand          = { path = "../../../third_party/rust-sgx-sdk/sgx_rand" }
 sgx_tprotected_fs = { path = "../../../third_party/rust-sgx-sdk/sgx_protected_fs/tfs" }
 sgx_tse           = { path = "../../../third_party/rust-sgx-sdk/sgx_tse" }
diff --git a/config/runtime.config.toml b/config/runtime.config.toml
index 96a7529..b1187eb 100644
--- a/config/runtime.config.toml
+++ b/config/runtime.config.toml
@@ -24,12 +24,12 @@
 frontend       = { listen_address = "0.0.0.0:7777" }
 
 [internal_endpoints]
-authentication = { listen_address = "0.0.0.0:17776", advertised_address = "localhost:17776" }
-management     = { listen_address = "0.0.0.0:17777", advertised_address = "localhost:17777" }
-storage        = { listen_address = "0.0.0.0:17778", advertised_address = "localhost:17778" }
-access_control = { listen_address = "0.0.0.0:17779", advertised_address = "localhost:17779" }
-execution      = { listen_address = "0.0.0.0:17770", advertised_address = "localhost:17770" }
-scheduler      = { listen_address = "0.0.0.0:17780", advertised_address = "localhost:17780" }
+authentication = { listen_address = "0.0.0.0:17776", advertised_address = "https://localhost:17776" }
+management     = { listen_address = "0.0.0.0:17777", advertised_address = "https://localhost:17777" }
+storage        = { listen_address = "0.0.0.0:17778", advertised_address = "https://localhost:17778" }
+access_control = { listen_address = "0.0.0.0:17779", advertised_address = "https://localhost:17779" }
+execution      = { listen_address = "0.0.0.0:17770", advertised_address = "https://localhost:17770" }
+scheduler      = { listen_address = "0.0.0.0:17780", advertised_address = "https://localhost:17780" }
 
 [audit]
 enclave_info = { path = "enclave_info.toml" }
diff --git a/docs/service-internals.md b/docs/service-internals.md
index 02fd2d5..3743ba0 100644
--- a/docs/service-internals.md
+++ b/docs/service-internals.md
@@ -42,13 +42,7 @@
 
 With this definition, the build system will help to generate utility functions,
 traits, and structures for clients to send RPC requests, and for service to
-implement functions of handling requests. This is done by a build time tool
-called [`proto_gen`](https://github.com/apache/incubator-teaclave/tree/master/services/proto/proto_gen).
-
-There is another layer in the `teaclave_proto` crate to help convert protobuf's
-simple data type to Rust's more concise data type. For example, a URL is defined
-in the string type in protobuf, while in Rust we can use the `Url` struct to
-store a URL.
+implement functions of handling requests. This is done by [`tonic_build`](https://github.com/hyperium/tonic/tree/master/tonic-build).
 
 For more protocol definitions for other services, please see proto files in
 the [`proto` directory](https://github.com/apache/incubator-teaclave/tree/master/services/proto/src/proto).
@@ -113,16 +107,16 @@
     .generate_and_endorse()?
     .attested_tls_config()
     .ok_or_else(|| anyhow!("cannot get attested TLS config"))?;
-let server_config = SgxTrustedTlsServerConfig::from_attested_tls_config(attested_tls_config)?;
-
-let mut server = SgxTrustedTlsServer::<
-    TeaclaveAuthenticationApiResponse,
-    TeaclaveAuthenticationApiRequest,
->::new(addr, server_config);
+let server_config = SgxTrustedTlsServerConfig::from_attested_tls_config(attested_tls_config)?.into();
 
 let service = api_service::TeaclaveAuthenticationApiService::new(db_client, jwt_secret);
 
-match server.start(service) {}
+Server::builder()
+    .tls_config(tls_config)
+    .map_err(|_| anyhow!("TeaclaveAuthenticationApiServer tls config error"))?
+    .add_service(TeaclaveAuthenticationApiServer::new(service))
+    .serve(addr)
+    .await?;
 ```
 
 ## Topology
diff --git a/examples/c/utils.h b/examples/c/utils.h
index 7901fa7..61f8937 100644
--- a/examples/c/utils.h
+++ b/examples/c/utils.h
@@ -18,8 +18,8 @@
  *
  */
 
-const char *authentication_service_address = "localhost:7776";
-const char *frontend_service_address = "localhost:7777";
+const char *authentication_service_address = "https://localhost:7776";
+const char *frontend_service_address = "https://localhost:7777";
 const char *enclave_info_path = "../../release/services/enclave_info.toml";
 #ifdef DCAP
 const char *as_root_ca_cert_path = "../../keys/dcap_root_ca_cert.pem";
diff --git a/examples/rust/builtin_echo/Cargo.lock b/examples/rust/builtin_echo/Cargo.lock
index 0603488..2e06e3a 100644
--- a/examples/rust/builtin_echo/Cargo.lock
+++ b/examples/rust/builtin_echo/Cargo.lock
@@ -3,6 +3,12 @@
 version = 3
 
 [[package]]
+name = "adler"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
+
+[[package]]
 name = "aho-corasick"
 version = "0.7.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -18,6 +24,39 @@
 checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6"
 
 [[package]]
+name = "async-stream"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ad445822218ce64be7a341abfb0b1ea43b5c23aa83902542a4542e78309d8e5e"
+dependencies = [
+ "async-stream-impl",
+ "futures-core",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "async-stream-impl"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e4655ae1a7b0cdf149156f780c5bf3f1352bc53cbd9e0a361a7ef7b22947e965"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.105",
+]
+
+[[package]]
+name = "async-trait"
+version = "0.1.68"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.12",
+]
+
+[[package]]
 name = "autocfg"
 version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -42,6 +81,12 @@
 checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
 
 [[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
 name = "builtin_echo"
 version = "0.5.1"
 dependencies = [
@@ -91,12 +136,67 @@
 ]
 
 [[package]]
+name = "crc32fast"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
+dependencies = [
+ "cfg-if 1.0.0",
+]
+
+[[package]]
 name = "either"
 version = "1.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
 
 [[package]]
+name = "errno"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50d6a0976c999d473fe89ad888d5a284e55366d9dc9038b1ba2aa15128c4afa0"
+dependencies = [
+ "errno-dragonfly",
+ "libc",
+ "windows-sys",
+]
+
+[[package]]
+name = "errno-dragonfly"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
+dependencies = [
+ "cc",
+ "libc",
+]
+
+[[package]]
+name = "fastrand"
+version = "1.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be"
+dependencies = [
+ "instant",
+]
+
+[[package]]
+name = "fixedbitset"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
+
+[[package]]
+name = "flate2"
+version = "1.0.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841"
+dependencies = [
+ "crc32fast",
+ "miniz_oxide",
+]
+
+[[package]]
 name = "fnv"
 version = "1.0.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -112,6 +212,45 @@
 ]
 
 [[package]]
+name = "futures-channel"
+version = "0.3.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2"
+dependencies = [
+ "futures-core",
+]
+
+[[package]]
+name = "futures-core"
+version = "0.3.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c"
+
+[[package]]
+name = "futures-sink"
+version = "0.3.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e"
+
+[[package]]
+name = "futures-task"
+version = "0.3.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65"
+
+[[package]]
+name = "futures-util"
+version = "0.3.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533"
+dependencies = [
+ "futures-core",
+ "futures-task",
+ "pin-project-lite",
+ "pin-utils",
+]
+
+[[package]]
 name = "getrandom"
 version = "0.2.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -123,6 +262,40 @@
 ]
 
 [[package]]
+name = "h2"
+version = "0.3.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5be7b54589b581f624f566bf5d8eb2bab1db736c51528720b6bd36b96b55924d"
+dependencies = [
+ "bytes",
+ "fnv",
+ "futures-core",
+ "futures-sink",
+ "futures-util",
+ "http",
+ "indexmap",
+ "slab",
+ "tokio",
+ "tokio-util 0.7.7",
+ "tracing",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
+
+[[package]]
+name = "heck"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
+dependencies = [
+ "unicode-segmentation",
+]
+
+[[package]]
 name = "hermit-abi"
 version = "0.1.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -132,6 +305,12 @@
 ]
 
 [[package]]
+name = "hermit-abi"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
+
+[[package]]
 name = "hex"
 version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -149,12 +328,65 @@
 ]
 
 [[package]]
+name = "http-body"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1"
+dependencies = [
+ "bytes",
+ "http",
+ "pin-project-lite",
+]
+
+[[package]]
 name = "httparse"
 version = "1.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
 
 [[package]]
+name = "httpdate"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
+
+[[package]]
+name = "hyper"
+version = "0.14.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cc5e554ff619822309ffd57d8734d77cd5ce6238bc956f037ea06c58238c9899"
+dependencies = [
+ "bytes",
+ "futures-channel",
+ "futures-core",
+ "futures-util",
+ "h2",
+ "http",
+ "http-body",
+ "httparse",
+ "httpdate",
+ "itoa",
+ "pin-project-lite",
+ "socket2",
+ "tokio",
+ "tower-service",
+ "tracing",
+ "want",
+]
+
+[[package]]
+name = "hyper-timeout"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1"
+dependencies = [
+ "hyper",
+ "pin-project-lite",
+ "tokio",
+ "tokio-io-timeout",
+]
+
+[[package]]
 name = "idna"
 version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -165,6 +397,36 @@
 ]
 
 [[package]]
+name = "indexmap"
+version = "1.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
+dependencies = [
+ "autocfg",
+ "hashbrown",
+]
+
+[[package]]
+name = "instant"
+version = "0.1.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
+dependencies = [
+ "cfg-if 1.0.0",
+]
+
+[[package]]
+name = "io-lifetimes"
+version = "1.0.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09270fd4fa1111bc614ed2246c7ef56239a3063d5be0d1ec3b589c505d400aeb"
+dependencies = [
+ "hermit-abi 0.3.1",
+ "libc",
+ "windows-sys",
+]
+
+[[package]]
 name = "itertools"
 version = "0.10.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -196,9 +458,15 @@
 
 [[package]]
 name = "libc"
-version = "0.2.138"
+version = "0.2.140"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
+checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
+
+[[package]]
+name = "linux-raw-sys"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f"
 
 [[package]]
 name = "log"
@@ -216,6 +484,33 @@
 checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
 
 [[package]]
+name = "miniz_oxide"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
+dependencies = [
+ "adler",
+]
+
+[[package]]
+name = "mio"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9"
+dependencies = [
+ "libc",
+ "log",
+ "wasi",
+ "windows-sys",
+]
+
+[[package]]
+name = "multimap"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a"
+
+[[package]]
 name = "num-bigint"
 version = "0.2.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -251,7 +546,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5"
 dependencies = [
- "hermit-abi",
+ "hermit-abi 0.1.19",
  "libc",
 ]
 
@@ -279,6 +574,48 @@
 checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
 
 [[package]]
+name = "petgraph"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4"
+dependencies = [
+ "fixedbitset",
+ "indexmap",
+]
+
+[[package]]
+name = "pin-project"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc"
+dependencies = [
+ "pin-project-internal",
+]
+
+[[package]]
+name = "pin-project-internal"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.105",
+]
+
+[[package]]
+name = "pin-project-lite"
+version = "0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
+
+[[package]]
+name = "pin-utils"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
+
+[[package]]
 name = "ppv-lite86"
 version = "0.2.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -286,41 +623,71 @@
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.47"
+version = "1.0.54"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
+checksum = "e472a104799c74b514a57226160104aa483546de37e839ec50e3c2e41dd87534"
 dependencies = [
  "unicode-ident",
 ]
 
 [[package]]
 name = "prost"
-version = "0.11.8"
+version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e48e50df39172a3e7eb17e14642445da64996989bc212b583015435d39a58537"
+checksum = "444879275cb4fd84958b1a1d5420d15e6fcf7c235fe47f053c9c2a80aceb6001"
 dependencies = [
  "bytes",
  "prost-derive",
 ]
 
 [[package]]
-name = "prost-derive"
-version = "0.11.8"
+name = "prost-build"
+version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ea9b0f8cbe5e15a8a042d030bd96668db28ecb567ec37d691971ff5731d2b1b"
+checksum = "62941722fb675d463659e49c4f3fe1fe792ff24fe5bbaa9c08cd3b98a1c354f5"
+dependencies = [
+ "bytes",
+ "heck",
+ "itertools",
+ "lazy_static",
+ "log",
+ "multimap",
+ "petgraph",
+ "prost",
+ "prost-types",
+ "regex",
+ "tempfile",
+ "which",
+]
+
+[[package]]
+name = "prost-derive"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f9cc1a3263e07e0bf68e96268f37665207b49560d98739662cdfaae215c720fe"
 dependencies = [
  "anyhow",
  "itertools",
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.105",
+]
+
+[[package]]
+name = "prost-types"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "534b7a0e836e3c482d2693070f982e39e7611da9695d4d1f5a4b186b51faef0a"
+dependencies = [
+ "bytes",
+ "prost",
 ]
 
 [[package]]
 name = "quote"
-version = "1.0.21"
+version = "1.0.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
+checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
 dependencies = [
  "proc-macro2",
 ]
@@ -365,6 +732,15 @@
 ]
 
 [[package]]
+name = "redox_syscall"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
 name = "regex"
 version = "1.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -397,12 +773,26 @@
 ]
 
 [[package]]
-name = "rustls"
-version = "0.17.0"
+name = "rustix"
+version = "0.37.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0d4a31f5d68413404705d6982529b0e11a9aacd4839d1d6222ee3b8cb4015e1"
+checksum = "0e78cc525325c06b4a7ff02db283472f3c042b7ff0c391f96c6d5ac6f4f91b75"
 dependencies = [
- "base64 0.11.0",
+ "bitflags",
+ "errno",
+ "io-lifetimes",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys",
+]
+
+[[package]]
+name = "rustls"
+version = "0.19.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "35edb675feee39aec9c99fa5ff985081995a06d594114ae14cbe797ad7b7a6d7"
+dependencies = [
+ "base64 0.13.1",
  "log",
  "ring",
  "sct",
@@ -442,7 +832,7 @@
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.105",
 ]
 
 [[package]]
@@ -531,6 +921,25 @@
 checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012"
 
 [[package]]
+name = "slab"
+version = "0.4.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "socket2"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662"
+dependencies = [
+ "libc",
+ "winapi",
+]
+
+[[package]]
 name = "spin"
 version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -548,6 +957,17 @@
 ]
 
 [[package]]
+name = "syn"
+version = "2.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "79d9531f94112cfc3e4c8f5f02cb2b58f72c97b7efd85f70203cc6d8efda5927"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
 name = "teaclave_attestation"
 version = "0.5.1"
 dependencies = [
@@ -588,6 +1008,7 @@
  "teaclave_proto",
  "teaclave_rpc",
  "teaclave_types",
+ "tokio",
  "url",
 ]
 
@@ -620,16 +1041,14 @@
 version = "0.5.1"
 dependencies = [
  "anyhow",
- "base64 0.13.1",
- "cfg-if 0.1.10",
  "prost",
- "rand",
  "serde",
  "serde_json",
  "sgx_types",
  "teaclave_crypto",
- "teaclave_rpc",
  "teaclave_types",
+ "tonic",
+ "tonic-build",
  "url",
  "uuid",
 ]
@@ -639,30 +1058,15 @@
 version = "0.5.1"
 dependencies = [
  "anyhow",
- "cfg-if 0.1.10",
- "http",
  "log",
  "rustls",
- "serde",
- "serde_json",
  "teaclave_attestation",
- "teaclave_rpc_proc_macro",
  "teaclave_types",
- "thiserror",
- "threadpool",
+ "tonic",
  "webpki",
 ]
 
 [[package]]
-name = "teaclave_rpc_proc_macro"
-version = "0.5.1"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
 name = "teaclave_types"
 version = "0.5.1"
 dependencies = [
@@ -678,11 +1082,25 @@
  "teaclave_crypto",
  "thiserror",
  "toml",
+ "tonic",
  "url",
  "uuid",
 ]
 
 [[package]]
+name = "tempfile"
+version = "3.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998"
+dependencies = [
+ "cfg-if 1.0.0",
+ "fastrand",
+ "redox_syscall",
+ "rustix",
+ "windows-sys",
+]
+
+[[package]]
 name = "thiserror"
 version = "1.0.37"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -699,16 +1117,7 @@
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
-]
-
-[[package]]
-name = "threadpool"
-version = "1.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa"
-dependencies = [
- "num_cpus",
+ "syn 1.0.105",
 ]
 
 [[package]]
@@ -727,6 +1136,94 @@
 checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
 
 [[package]]
+name = "tokio"
+version = "1.27.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d0de47a4eecbe11f498978a9b29d792f0d2692d1dd003650c24c76510e3bc001"
+dependencies = [
+ "autocfg",
+ "bytes",
+ "libc",
+ "mio",
+ "num_cpus",
+ "pin-project-lite",
+ "socket2",
+ "tokio-macros",
+ "windows-sys",
+]
+
+[[package]]
+name = "tokio-io-timeout"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf"
+dependencies = [
+ "pin-project-lite",
+ "tokio",
+]
+
+[[package]]
+name = "tokio-macros"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "61a573bdc87985e9d6ddeed1b3d864e8a302c847e40d647746df2f1de209d1ce"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.12",
+]
+
+[[package]]
+name = "tokio-rustls"
+version = "0.22.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6"
+dependencies = [
+ "rustls",
+ "tokio",
+ "webpki",
+]
+
+[[package]]
+name = "tokio-stream"
+version = "0.1.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8fb52b74f05dbf495a8fba459fdc331812b96aa086d9eb78101fa0d4569c3313"
+dependencies = [
+ "futures-core",
+ "pin-project-lite",
+ "tokio",
+]
+
+[[package]]
+name = "tokio-util"
+version = "0.6.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507"
+dependencies = [
+ "bytes",
+ "futures-core",
+ "futures-sink",
+ "log",
+ "pin-project-lite",
+ "tokio",
+]
+
+[[package]]
+name = "tokio-util"
+version = "0.7.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2"
+dependencies = [
+ "bytes",
+ "futures-core",
+ "futures-sink",
+ "pin-project-lite",
+ "tokio",
+ "tracing",
+]
+
+[[package]]
 name = "toml"
 version = "0.5.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -736,6 +1233,132 @@
 ]
 
 [[package]]
+name = "tonic"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ff08f4649d10a70ffa3522ca559031285d8e421d727ac85c60825761818f5d0a"
+dependencies = [
+ "async-stream",
+ "async-trait",
+ "base64 0.13.1",
+ "bytes",
+ "flate2",
+ "futures-core",
+ "futures-util",
+ "h2",
+ "http",
+ "http-body",
+ "hyper",
+ "hyper-timeout",
+ "percent-encoding",
+ "pin-project",
+ "prost",
+ "prost-derive",
+ "tokio",
+ "tokio-rustls",
+ "tokio-stream",
+ "tokio-util 0.6.10",
+ "tower",
+ "tower-layer",
+ "tower-service",
+ "tracing",
+ "tracing-futures",
+]
+
+[[package]]
+name = "tonic-build"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9403f1bafde247186684b230dc6f38b5cd514584e8bec1dd32514be4745fa757"
+dependencies = [
+ "proc-macro2",
+ "prost-build",
+ "quote",
+ "syn 1.0.105",
+]
+
+[[package]]
+name = "tower"
+version = "0.4.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
+dependencies = [
+ "futures-core",
+ "futures-util",
+ "indexmap",
+ "pin-project",
+ "pin-project-lite",
+ "rand",
+ "slab",
+ "tokio",
+ "tokio-util 0.7.7",
+ "tower-layer",
+ "tower-service",
+ "tracing",
+]
+
+[[package]]
+name = "tower-layer"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0"
+
+[[package]]
+name = "tower-service"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
+
+[[package]]
+name = "tracing"
+version = "0.1.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
+dependencies = [
+ "cfg-if 1.0.0",
+ "log",
+ "pin-project-lite",
+ "tracing-attributes",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-attributes"
+version = "0.1.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.105",
+]
+
+[[package]]
+name = "tracing-core"
+version = "0.1.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a"
+dependencies = [
+ "once_cell",
+]
+
+[[package]]
+name = "tracing-futures"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2"
+dependencies = [
+ "pin-project",
+ "tracing",
+]
+
+[[package]]
+name = "try-lock"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
+
+[[package]]
 name = "unicode-bidi"
 version = "0.3.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -757,6 +1380,12 @@
 ]
 
 [[package]]
+name = "unicode-segmentation"
+version = "1.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36"
+
+[[package]]
 name = "untrusted"
 version = "0.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -786,6 +1415,16 @@
 ]
 
 [[package]]
+name = "want"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0"
+dependencies = [
+ "log",
+ "try-lock",
+]
+
+[[package]]
 name = "wasi"
 version = "0.11.0+wasi-snapshot-preview1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -812,7 +1451,7 @@
  "once_cell",
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.105",
  "wasm-bindgen-shared",
 ]
 
@@ -834,7 +1473,7 @@
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.105",
  "wasm-bindgen-backend",
  "wasm-bindgen-shared",
 ]
@@ -875,6 +1514,17 @@
 ]
 
 [[package]]
+name = "which"
+version = "4.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269"
+dependencies = [
+ "either",
+ "libc",
+ "once_cell",
+]
+
+[[package]]
 name = "winapi"
 version = "0.3.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -897,6 +1547,72 @@
 checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 
 [[package]]
+name = "windows-sys"
+version = "0.45.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
+
+[[package]]
 name = "yasna"
 version = "0.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/examples/rust/builtin_echo/src/main.rs b/examples/rust/builtin_echo/src/main.rs
index f595274..6f3d1c1 100644
--- a/examples/rust/builtin_echo/src/main.rs
+++ b/examples/rust/builtin_echo/src/main.rs
@@ -43,7 +43,7 @@
     let bytes = fs::read(AS_ROOT_CA_CERT_PATH)?;
     let as_root_ca_cert = pem::parse(bytes)?.contents;
     let mut client = teaclave_client_sdk::AuthenticationService::connect(
-        "localhost:7776",
+        "https://localhost:7776",
         &enclave_info,
         &as_root_ca_cert,
     )?;
@@ -52,7 +52,7 @@
     let token = client.user_login(USER_ID, USER_PASSWORD)?;
 
     let mut client = teaclave_client_sdk::FrontendService::connect(
-        "localhost:7777",
+        "https://localhost:7777",
         &enclave_info,
         &as_root_ca_cert,
     )?;
diff --git a/examples/rust/builtin_ordered_set_intersect/Cargo.lock b/examples/rust/builtin_ordered_set_intersect/Cargo.lock
index a0dcae1..05a3542 100644
--- a/examples/rust/builtin_ordered_set_intersect/Cargo.lock
+++ b/examples/rust/builtin_ordered_set_intersect/Cargo.lock
@@ -3,6 +3,12 @@
 version = 3
 
 [[package]]
+name = "adler"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
+
+[[package]]
 name = "aho-corasick"
 version = "0.7.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -18,6 +24,39 @@
 checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6"
 
 [[package]]
+name = "async-stream"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ad445822218ce64be7a341abfb0b1ea43b5c23aa83902542a4542e78309d8e5e"
+dependencies = [
+ "async-stream-impl",
+ "futures-core",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "async-stream-impl"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e4655ae1a7b0cdf149156f780c5bf3f1352bc53cbd9e0a361a7ef7b22947e965"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.105",
+]
+
+[[package]]
+name = "async-trait"
+version = "0.1.68"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.12",
+]
+
+[[package]]
 name = "autocfg"
 version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -42,6 +81,12 @@
 checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
 
 [[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
 name = "builtin_ordered_set_intersect"
 version = "0.5.1"
 dependencies = [
@@ -91,12 +136,67 @@
 ]
 
 [[package]]
+name = "crc32fast"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
+dependencies = [
+ "cfg-if 1.0.0",
+]
+
+[[package]]
 name = "either"
 version = "1.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
 
 [[package]]
+name = "errno"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50d6a0976c999d473fe89ad888d5a284e55366d9dc9038b1ba2aa15128c4afa0"
+dependencies = [
+ "errno-dragonfly",
+ "libc",
+ "windows-sys",
+]
+
+[[package]]
+name = "errno-dragonfly"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
+dependencies = [
+ "cc",
+ "libc",
+]
+
+[[package]]
+name = "fastrand"
+version = "1.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be"
+dependencies = [
+ "instant",
+]
+
+[[package]]
+name = "fixedbitset"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
+
+[[package]]
+name = "flate2"
+version = "1.0.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841"
+dependencies = [
+ "crc32fast",
+ "miniz_oxide",
+]
+
+[[package]]
 name = "fnv"
 version = "1.0.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -112,6 +212,45 @@
 ]
 
 [[package]]
+name = "futures-channel"
+version = "0.3.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2"
+dependencies = [
+ "futures-core",
+]
+
+[[package]]
+name = "futures-core"
+version = "0.3.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c"
+
+[[package]]
+name = "futures-sink"
+version = "0.3.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e"
+
+[[package]]
+name = "futures-task"
+version = "0.3.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65"
+
+[[package]]
+name = "futures-util"
+version = "0.3.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533"
+dependencies = [
+ "futures-core",
+ "futures-task",
+ "pin-project-lite",
+ "pin-utils",
+]
+
+[[package]]
 name = "getrandom"
 version = "0.2.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -123,6 +262,40 @@
 ]
 
 [[package]]
+name = "h2"
+version = "0.3.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5be7b54589b581f624f566bf5d8eb2bab1db736c51528720b6bd36b96b55924d"
+dependencies = [
+ "bytes",
+ "fnv",
+ "futures-core",
+ "futures-sink",
+ "futures-util",
+ "http",
+ "indexmap",
+ "slab",
+ "tokio",
+ "tokio-util 0.7.7",
+ "tracing",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
+
+[[package]]
+name = "heck"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
+dependencies = [
+ "unicode-segmentation",
+]
+
+[[package]]
 name = "hermit-abi"
 version = "0.1.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -132,6 +305,12 @@
 ]
 
 [[package]]
+name = "hermit-abi"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
+
+[[package]]
 name = "hex"
 version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -149,12 +328,65 @@
 ]
 
 [[package]]
+name = "http-body"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1"
+dependencies = [
+ "bytes",
+ "http",
+ "pin-project-lite",
+]
+
+[[package]]
 name = "httparse"
 version = "1.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
 
 [[package]]
+name = "httpdate"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
+
+[[package]]
+name = "hyper"
+version = "0.14.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cc5e554ff619822309ffd57d8734d77cd5ce6238bc956f037ea06c58238c9899"
+dependencies = [
+ "bytes",
+ "futures-channel",
+ "futures-core",
+ "futures-util",
+ "h2",
+ "http",
+ "http-body",
+ "httparse",
+ "httpdate",
+ "itoa",
+ "pin-project-lite",
+ "socket2",
+ "tokio",
+ "tower-service",
+ "tracing",
+ "want",
+]
+
+[[package]]
+name = "hyper-timeout"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1"
+dependencies = [
+ "hyper",
+ "pin-project-lite",
+ "tokio",
+ "tokio-io-timeout",
+]
+
+[[package]]
 name = "idna"
 version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -165,6 +397,36 @@
 ]
 
 [[package]]
+name = "indexmap"
+version = "1.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
+dependencies = [
+ "autocfg",
+ "hashbrown",
+]
+
+[[package]]
+name = "instant"
+version = "0.1.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
+dependencies = [
+ "cfg-if 1.0.0",
+]
+
+[[package]]
+name = "io-lifetimes"
+version = "1.0.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09270fd4fa1111bc614ed2246c7ef56239a3063d5be0d1ec3b589c505d400aeb"
+dependencies = [
+ "hermit-abi 0.3.1",
+ "libc",
+ "windows-sys",
+]
+
+[[package]]
 name = "itertools"
 version = "0.10.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -196,9 +458,15 @@
 
 [[package]]
 name = "libc"
-version = "0.2.138"
+version = "0.2.140"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
+checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
+
+[[package]]
+name = "linux-raw-sys"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f"
 
 [[package]]
 name = "log"
@@ -216,6 +484,33 @@
 checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
 
 [[package]]
+name = "miniz_oxide"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
+dependencies = [
+ "adler",
+]
+
+[[package]]
+name = "mio"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9"
+dependencies = [
+ "libc",
+ "log",
+ "wasi",
+ "windows-sys",
+]
+
+[[package]]
+name = "multimap"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a"
+
+[[package]]
 name = "num-bigint"
 version = "0.2.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -251,7 +546,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5"
 dependencies = [
- "hermit-abi",
+ "hermit-abi 0.1.19",
  "libc",
 ]
 
@@ -279,6 +574,48 @@
 checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
 
 [[package]]
+name = "petgraph"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4"
+dependencies = [
+ "fixedbitset",
+ "indexmap",
+]
+
+[[package]]
+name = "pin-project"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc"
+dependencies = [
+ "pin-project-internal",
+]
+
+[[package]]
+name = "pin-project-internal"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.105",
+]
+
+[[package]]
+name = "pin-project-lite"
+version = "0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
+
+[[package]]
+name = "pin-utils"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
+
+[[package]]
 name = "ppv-lite86"
 version = "0.2.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -286,41 +623,71 @@
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.47"
+version = "1.0.54"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
+checksum = "e472a104799c74b514a57226160104aa483546de37e839ec50e3c2e41dd87534"
 dependencies = [
  "unicode-ident",
 ]
 
 [[package]]
 name = "prost"
-version = "0.11.8"
+version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e48e50df39172a3e7eb17e14642445da64996989bc212b583015435d39a58537"
+checksum = "444879275cb4fd84958b1a1d5420d15e6fcf7c235fe47f053c9c2a80aceb6001"
 dependencies = [
  "bytes",
  "prost-derive",
 ]
 
 [[package]]
-name = "prost-derive"
-version = "0.11.8"
+name = "prost-build"
+version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ea9b0f8cbe5e15a8a042d030bd96668db28ecb567ec37d691971ff5731d2b1b"
+checksum = "62941722fb675d463659e49c4f3fe1fe792ff24fe5bbaa9c08cd3b98a1c354f5"
+dependencies = [
+ "bytes",
+ "heck",
+ "itertools",
+ "lazy_static",
+ "log",
+ "multimap",
+ "petgraph",
+ "prost",
+ "prost-types",
+ "regex",
+ "tempfile",
+ "which",
+]
+
+[[package]]
+name = "prost-derive"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f9cc1a3263e07e0bf68e96268f37665207b49560d98739662cdfaae215c720fe"
 dependencies = [
  "anyhow",
  "itertools",
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.105",
+]
+
+[[package]]
+name = "prost-types"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "534b7a0e836e3c482d2693070f982e39e7611da9695d4d1f5a4b186b51faef0a"
+dependencies = [
+ "bytes",
+ "prost",
 ]
 
 [[package]]
 name = "quote"
-version = "1.0.21"
+version = "1.0.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
+checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
 dependencies = [
  "proc-macro2",
 ]
@@ -365,6 +732,15 @@
 ]
 
 [[package]]
+name = "redox_syscall"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
 name = "regex"
 version = "1.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -397,12 +773,26 @@
 ]
 
 [[package]]
-name = "rustls"
-version = "0.17.0"
+name = "rustix"
+version = "0.37.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0d4a31f5d68413404705d6982529b0e11a9aacd4839d1d6222ee3b8cb4015e1"
+checksum = "0e78cc525325c06b4a7ff02db283472f3c042b7ff0c391f96c6d5ac6f4f91b75"
 dependencies = [
- "base64 0.11.0",
+ "bitflags",
+ "errno",
+ "io-lifetimes",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys",
+]
+
+[[package]]
+name = "rustls"
+version = "0.19.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "35edb675feee39aec9c99fa5ff985081995a06d594114ae14cbe797ad7b7a6d7"
+dependencies = [
+ "base64 0.13.1",
  "log",
  "ring",
  "sct",
@@ -442,7 +832,7 @@
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.105",
 ]
 
 [[package]]
@@ -531,6 +921,25 @@
 checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012"
 
 [[package]]
+name = "slab"
+version = "0.4.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "socket2"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662"
+dependencies = [
+ "libc",
+ "winapi",
+]
+
+[[package]]
 name = "spin"
 version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -548,6 +957,17 @@
 ]
 
 [[package]]
+name = "syn"
+version = "2.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "79d9531f94112cfc3e4c8f5f02cb2b58f72c97b7efd85f70203cc6d8efda5927"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
 name = "teaclave_attestation"
 version = "0.5.1"
 dependencies = [
@@ -588,6 +1008,7 @@
  "teaclave_proto",
  "teaclave_rpc",
  "teaclave_types",
+ "tokio",
  "url",
 ]
 
@@ -620,16 +1041,14 @@
 version = "0.5.1"
 dependencies = [
  "anyhow",
- "base64 0.13.1",
- "cfg-if 0.1.10",
  "prost",
- "rand",
  "serde",
  "serde_json",
  "sgx_types",
  "teaclave_crypto",
- "teaclave_rpc",
  "teaclave_types",
+ "tonic",
+ "tonic-build",
  "url",
  "uuid",
 ]
@@ -639,30 +1058,15 @@
 version = "0.5.1"
 dependencies = [
  "anyhow",
- "cfg-if 0.1.10",
- "http",
  "log",
  "rustls",
- "serde",
- "serde_json",
  "teaclave_attestation",
- "teaclave_rpc_proc_macro",
  "teaclave_types",
- "thiserror",
- "threadpool",
+ "tonic",
  "webpki",
 ]
 
 [[package]]
-name = "teaclave_rpc_proc_macro"
-version = "0.5.1"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
 name = "teaclave_types"
 version = "0.5.1"
 dependencies = [
@@ -678,11 +1082,25 @@
  "teaclave_crypto",
  "thiserror",
  "toml",
+ "tonic",
  "url",
  "uuid",
 ]
 
 [[package]]
+name = "tempfile"
+version = "3.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998"
+dependencies = [
+ "cfg-if 1.0.0",
+ "fastrand",
+ "redox_syscall",
+ "rustix",
+ "windows-sys",
+]
+
+[[package]]
 name = "thiserror"
 version = "1.0.37"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -699,16 +1117,7 @@
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
-]
-
-[[package]]
-name = "threadpool"
-version = "1.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa"
-dependencies = [
- "num_cpus",
+ "syn 1.0.105",
 ]
 
 [[package]]
@@ -727,6 +1136,94 @@
 checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
 
 [[package]]
+name = "tokio"
+version = "1.27.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d0de47a4eecbe11f498978a9b29d792f0d2692d1dd003650c24c76510e3bc001"
+dependencies = [
+ "autocfg",
+ "bytes",
+ "libc",
+ "mio",
+ "num_cpus",
+ "pin-project-lite",
+ "socket2",
+ "tokio-macros",
+ "windows-sys",
+]
+
+[[package]]
+name = "tokio-io-timeout"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf"
+dependencies = [
+ "pin-project-lite",
+ "tokio",
+]
+
+[[package]]
+name = "tokio-macros"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "61a573bdc87985e9d6ddeed1b3d864e8a302c847e40d647746df2f1de209d1ce"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.12",
+]
+
+[[package]]
+name = "tokio-rustls"
+version = "0.22.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6"
+dependencies = [
+ "rustls",
+ "tokio",
+ "webpki",
+]
+
+[[package]]
+name = "tokio-stream"
+version = "0.1.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8fb52b74f05dbf495a8fba459fdc331812b96aa086d9eb78101fa0d4569c3313"
+dependencies = [
+ "futures-core",
+ "pin-project-lite",
+ "tokio",
+]
+
+[[package]]
+name = "tokio-util"
+version = "0.6.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507"
+dependencies = [
+ "bytes",
+ "futures-core",
+ "futures-sink",
+ "log",
+ "pin-project-lite",
+ "tokio",
+]
+
+[[package]]
+name = "tokio-util"
+version = "0.7.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2"
+dependencies = [
+ "bytes",
+ "futures-core",
+ "futures-sink",
+ "pin-project-lite",
+ "tokio",
+ "tracing",
+]
+
+[[package]]
 name = "toml"
 version = "0.5.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -736,6 +1233,132 @@
 ]
 
 [[package]]
+name = "tonic"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ff08f4649d10a70ffa3522ca559031285d8e421d727ac85c60825761818f5d0a"
+dependencies = [
+ "async-stream",
+ "async-trait",
+ "base64 0.13.1",
+ "bytes",
+ "flate2",
+ "futures-core",
+ "futures-util",
+ "h2",
+ "http",
+ "http-body",
+ "hyper",
+ "hyper-timeout",
+ "percent-encoding",
+ "pin-project",
+ "prost",
+ "prost-derive",
+ "tokio",
+ "tokio-rustls",
+ "tokio-stream",
+ "tokio-util 0.6.10",
+ "tower",
+ "tower-layer",
+ "tower-service",
+ "tracing",
+ "tracing-futures",
+]
+
+[[package]]
+name = "tonic-build"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9403f1bafde247186684b230dc6f38b5cd514584e8bec1dd32514be4745fa757"
+dependencies = [
+ "proc-macro2",
+ "prost-build",
+ "quote",
+ "syn 1.0.105",
+]
+
+[[package]]
+name = "tower"
+version = "0.4.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
+dependencies = [
+ "futures-core",
+ "futures-util",
+ "indexmap",
+ "pin-project",
+ "pin-project-lite",
+ "rand",
+ "slab",
+ "tokio",
+ "tokio-util 0.7.7",
+ "tower-layer",
+ "tower-service",
+ "tracing",
+]
+
+[[package]]
+name = "tower-layer"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0"
+
+[[package]]
+name = "tower-service"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
+
+[[package]]
+name = "tracing"
+version = "0.1.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
+dependencies = [
+ "cfg-if 1.0.0",
+ "log",
+ "pin-project-lite",
+ "tracing-attributes",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-attributes"
+version = "0.1.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.105",
+]
+
+[[package]]
+name = "tracing-core"
+version = "0.1.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a"
+dependencies = [
+ "once_cell",
+]
+
+[[package]]
+name = "tracing-futures"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2"
+dependencies = [
+ "pin-project",
+ "tracing",
+]
+
+[[package]]
+name = "try-lock"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
+
+[[package]]
 name = "unicode-bidi"
 version = "0.3.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -757,6 +1380,12 @@
 ]
 
 [[package]]
+name = "unicode-segmentation"
+version = "1.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36"
+
+[[package]]
 name = "untrusted"
 version = "0.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -786,6 +1415,16 @@
 ]
 
 [[package]]
+name = "want"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0"
+dependencies = [
+ "log",
+ "try-lock",
+]
+
+[[package]]
 name = "wasi"
 version = "0.11.0+wasi-snapshot-preview1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -812,7 +1451,7 @@
  "once_cell",
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.105",
  "wasm-bindgen-shared",
 ]
 
@@ -834,7 +1473,7 @@
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.105",
  "wasm-bindgen-backend",
  "wasm-bindgen-shared",
 ]
@@ -875,6 +1514,17 @@
 ]
 
 [[package]]
+name = "which"
+version = "4.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269"
+dependencies = [
+ "either",
+ "libc",
+ "once_cell",
+]
+
+[[package]]
 name = "winapi"
 version = "0.3.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -897,6 +1547,72 @@
 checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 
 [[package]]
+name = "windows-sys"
+version = "0.45.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
+
+[[package]]
 name = "yasna"
 version = "0.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/examples/rust/builtin_ordered_set_intersect/src/main.rs b/examples/rust/builtin_ordered_set_intersect/src/main.rs
index 75ead1f..55d0e02 100644
--- a/examples/rust/builtin_ordered_set_intersect/src/main.rs
+++ b/examples/rust/builtin_ordered_set_intersect/src/main.rs
@@ -64,7 +64,7 @@
         let bytes = fs::read(AS_ROOT_CA_CERT_PATH)?;
         let as_root_ca_cert = pem::parse(bytes)?.contents;
         let mut client = teaclave_client_sdk::AuthenticationService::connect(
-            "localhost:7776",
+            "https://localhost:7776",
             &enclave_info,
             &as_root_ca_cert,
         )?;
@@ -91,7 +91,7 @@
         let bytes = fs::read(AS_ROOT_CA_CERT_PATH)?;
         let as_root_ca_cert = pem::parse(bytes)?.contents;
         let mut client = teaclave_client_sdk::AuthenticationService::connect(
-            "localhost:7776",
+            "https://localhost:7776",
             &enclave_info,
             &as_root_ca_cert,
         )?;
@@ -102,7 +102,7 @@
         let token = client.user_login(&user_data.user_id, &user_data.user_password)?;
 
         let mut client = teaclave_client_sdk::FrontendService::connect(
-            "localhost:7777",
+            "https://localhost:7777",
             &enclave_info,
             &as_root_ca_cert,
         )?;
diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml
index 7bb664c..42c649e 100644
--- a/rpc/Cargo.toml
+++ b/rpc/Cargo.toml
@@ -26,31 +26,24 @@
 [features]
 default = []
 app = [
-    "libc",
     "teaclave_types/app",
     "teaclave_attestation/app"
 ]
 mesalock_sgx = [
-    "sgx_libc",
     "teaclave_types/mesalock_sgx",
     "teaclave_attestation/mesalock_sgx",
 ]
+libos = [
+    "app",
+    "teaclave_attestation/libos",
+]
 
 [dependencies]
 anyhow     = { version = "1.0.26" }
-cfg-if     = { version = "0.1.9" }
-http       = { version = "0.2" }
-libc       = { version = "0.2.66", optional = true }
 log        = { version = "0.4.17", features = ["release_max_level_info"] }
 rustls     = { version = "0.19.0", features = ["dangerous_configuration"] }
-serde      = { version = "1.0.92", features = ["derive"] }
-serde_json = { version = "1.0.39" }
-thiserror  = { version = "1.0.9" }
-threadpool = { version = "1.8.0" }
+tonic      = { version = "0.6.1", features = ["tls", "compression"] }
 webpki     = { version = "0.21.0" }
 
 teaclave_types       = { path = "../types" }
 teaclave_attestation = { path = "../attestation" }
-teaclave_rpc_proc_macro = { path = "./proc_macro" }
-
-sgx_libc = { version = "2.0.0", optional = true }
diff --git a/rpc/README.md b/rpc/README.md
index d26e70b..1fca4db 100644
--- a/rpc/README.md
+++ b/rpc/README.md
@@ -1,43 +1,37 @@
----
-permalink: /docs/codebase/rpc
+--- 
+permalink: /docs/codebase/rpc 
 ---
 
 # RPC
 
-This directory contains an RPC implementation over attested TLS connection
-written in Rust, providing trusted channels to send and handle requests.
-RPC interfaces and request/response messages can be defined in ProtoBuf and
-used for generating Rust structs and traits to implement services or client
-function to send requests.
+This directory contains TLS configuration over an attested TLS connection,
+providing trusted channels to send and handle requests.
 
-Similar with other RPC frameworks, there are several concepts of RPC in
-Teaclave.
+Re-export [Tonic](https://github.com/hyperium/tonic) to support the general
+gRPC framework. `Tonic` is a gRPC over HTTP/2 implementation focused on high
+performance, interoperability, and flexibility.
 
 ## Channel and Client
 
-A channel in RPC represent a connection to the target service. Clients can use
-the channel to send requests. In Teaclave, we implement `SgxTrustedTlsChannel`,
-which can establish and attested a remote connection. For example, to connect
-the management service, you need to establish a trusted channel with the service
-first. Then, create a client of management service with the channel. At last,
-you can use this client to send requests like `InvokeTask`.
+A channel in gRPC represents a connection to the target service. Clients can
+use the channel to send requests. When constructing a client, you can use the
+`SgxTrustedTlsClientConfig` to set up TLS and attestation configurations so
+that we can establish and attest to a remote connection. For example, to
+connect the management service, you need to establish a trusted channel with
+the service first. Then, create a client for the management service with the
+channel. At last, you can use this client to send requests like `InvokeTask`.
 
-When constructing a client, you can use the `SgxTrustedTlsClientConfig` to setup
-TLS and attestation configs.
 
 ## Server and Service
 
-Server is an entity to listening a network address, processing incoming
-messages, and forwarding requests to certain service. Similar with channel in
-Teaclave, we implement `SgxTrustedTlsServer`, which can establish an attested TLS
-channel with clients.
+A server is an entity that listens to a network address, processes incoming
+messages, and forwards requests to certain services. Similar to the client, you
+can use `SgxTrustedTlsServerConfig` to set up TLS and attestation
+configurations for the channel with clients.
 
-Similar with the client, you can use `SgxTrustedTlsServerConfig` to setup TLS
-and attestation configs.
 
-## Protocol
+## Interceptor
 
-There are many RPC protocols that can be implemented in the RPC framework. Currently,
-there's only one simple protocol called `JsonProtocol`. Simply speaking, for
-the json protocol, one RPC message will contain a length of the following
-requests (in big endian) and a json serialized request.
+In Teaclave, we implement `CredentialService` based on the `Interceptor` trait
+to add a credential to the MetadataMap of each request before it is sent, so
+servers can check the authentication credential of each request.
diff --git a/rpc/proc_macro/Cargo.toml b/rpc/proc_macro/Cargo.toml
deleted file mode 100644
index 08ae693..0000000
--- a/rpc/proc_macro/Cargo.toml
+++ /dev/null
@@ -1,31 +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.
-
-[package]
-name = "teaclave_rpc_proc_macro"
-version = "0.5.1"
-authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
-license = "Apache-2.0"
-edition = "2021"
-
-[lib]
-proc-macro = true
-
-[dependencies]
-proc-macro2 = "1.0"
-quote = "1.0"
-syn = { version = "1.0", features = ["full"] }
diff --git a/rpc/proc_macro/src/lib.rs b/rpc/proc_macro/src/lib.rs
deleted file mode 100644
index ef2522b..0000000
--- a/rpc/proc_macro/src/lib.rs
+++ /dev/null
@@ -1,46 +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.
-
-extern crate proc_macro;
-use proc_macro2::{Ident, Span};
-use quote::quote;
-use syn::parse_macro_input;
-use syn::ItemStruct;
-
-use proc_macro::TokenStream;
-
-#[proc_macro_attribute]
-pub fn into_request(attr: TokenStream, input: TokenStream) -> TokenStream {
-    let attr_str = attr.to_string();
-    let splits: Vec<&str> = attr_str.split("::").map(|s| s.trim()).collect();
-    let name = Ident::new(splits[0], Span::call_site());
-    let item = Ident::new(splits[1], Span::call_site());
-    let f = parse_macro_input!(input as ItemStruct);
-    let struct_ident = &f.ident;
-    let q = quote!(
-    #f
-
-
-    impl teaclave_rpc::IntoRequest<#name> for #struct_ident {
-        fn into_request(self) -> teaclave_rpc::Request<#name> {
-            teaclave_rpc::Request::new(#name::#item(self.into()))
-        }
-    }
-    );
-
-    q.into()
-}
diff --git a/rpc/src/channel.rs b/rpc/src/channel.rs
deleted file mode 100644
index 63a18ef..0000000
--- a/rpc/src/channel.rs
+++ /dev/null
@@ -1,66 +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 crate::config::SgxTrustedTlsClientConfig;
-use crate::transport::{ClientTransport, SgxTrustedTlsTransport};
-use crate::Request;
-use anyhow::anyhow;
-use anyhow::Result;
-use http::Uri;
-use serde::{Deserialize, Serialize};
-use std::sync::Arc;
-
-pub struct SgxTrustedTlsChannel<U, V>
-where
-    U: Serialize + std::fmt::Debug,
-    V: for<'de> Deserialize<'de> + std::fmt::Debug,
-{
-    transport: SgxTrustedTlsTransport<rustls::ClientSession>,
-    maker: std::marker::PhantomData<(U, V)>,
-}
-
-impl<U, V> SgxTrustedTlsChannel<U, V>
-where
-    U: Serialize + std::fmt::Debug,
-    V: for<'de> Deserialize<'de> + std::fmt::Debug,
-{
-    pub fn new(
-        address: &str,
-        client_config: &SgxTrustedTlsClientConfig,
-    ) -> Result<SgxTrustedTlsChannel<U, V>> {
-        let uri = address.parse::<Uri>()?;
-        let hostname = uri.host().ok_or_else(|| anyhow!("Invalid hostname."))?;
-        let stream = std::net::TcpStream::connect(address)?;
-        let hostname = webpki::DNSNameRef::try_from_ascii_str(hostname)?;
-        let session =
-            rustls::ClientSession::new(&Arc::new(client_config.client_config.clone()), hostname);
-        let tls_stream = rustls::StreamOwned::new(session, stream);
-        let transport = SgxTrustedTlsTransport::new(tls_stream);
-
-        Ok(Self {
-            transport,
-            maker: std::marker::PhantomData::<(U, V)>,
-        })
-    }
-
-    pub fn invoke(
-        &mut self,
-        input: Request<U>,
-    ) -> teaclave_types::TeaclaveServiceResponseResult<V> {
-        self.transport.send(input)
-    }
-}
diff --git a/rpc/src/config.rs b/rpc/src/config.rs
index cb95269..10a5655 100644
--- a/rpc/src/config.rs
+++ b/rpc/src/config.rs
@@ -15,6 +15,7 @@
 // specific language governing permissions and limitations
 // under the License.
 
+use crate::transport::{ClientTlsConfig, ServerTlsConfig};
 use anyhow::{anyhow, bail, Result};
 use log::debug;
 use std::sync::{Arc, RwLock};
@@ -29,6 +30,9 @@
 use teaclave_attestation::AttestedTlsConfig;
 use teaclave_types::EnclaveAttr;
 
+// Yout should set the 'h2' negotiation flag for tonic grpc.
+pub const ALPN_H2: &str = "h2";
+
 #[derive(Clone)]
 pub struct SgxTrustedTlsServerConfig {
     server_config: rustls::ServerConfig,
@@ -79,7 +83,7 @@
     }
 
     // Disable this function for non-SGX targets.
-    #[cfg(feature = "mesalock_sgx")]
+    #[cfg(any(feature = "mesalock_sgx", feature = "libos"))]
     pub fn attestation_report_verifier(
         mut self,
         accepted_enclave_attrs: Vec<EnclaveAttr>,
@@ -133,6 +137,16 @@
     }
 }
 
+impl From<SgxTrustedTlsServerConfig> for ServerTlsConfig {
+    fn from(config: SgxTrustedTlsServerConfig) -> Self {
+        let mut config_service = config.server_config;
+        config_service.set_protocols(&[ALPN_H2.as_bytes().to_vec()]);
+        let mut tls_config = ServerTlsConfig::new();
+        let tls_config = tls_config.rustls_server_config(config_service);
+        tls_config.to_owned()
+    }
+}
+
 pub struct SgxTrustedTlsClientConfig {
     pub client_config: rustls::ClientConfig,
     pub attested_tls_config: Option<Arc<RwLock<AttestedTlsConfig>>>,
@@ -224,3 +238,12 @@
         Ok(config)
     }
 }
+
+impl From<SgxTrustedTlsClientConfig> for ClientTlsConfig {
+    fn from(config: SgxTrustedTlsClientConfig) -> Self {
+        let mut client_config = config.client_config;
+        // Yout must set the 'h2' negotiation flag.
+        client_config.set_protocols(&[ALPN_H2.as_bytes().to_vec()]);
+        ClientTlsConfig::new().rustls_client_config(client_config)
+    }
+}
diff --git a/rpc/src/endpoint.rs b/rpc/src/endpoint.rs
deleted file mode 100644
index 3cba453..0000000
--- a/rpc/src/endpoint.rs
+++ /dev/null
@@ -1,51 +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 crate::channel::SgxTrustedTlsChannel;
-use crate::config::SgxTrustedTlsClientConfig;
-use anyhow::Result;
-use serde::{Deserialize, Serialize};
-
-pub struct Endpoint {
-    url: String,
-    config: SgxTrustedTlsClientConfig,
-}
-
-impl Endpoint {
-    pub fn new(url: &str) -> Self {
-        let config = SgxTrustedTlsClientConfig::new();
-        Self {
-            url: url.to_string(),
-            config,
-        }
-    }
-
-    pub fn connect<U, V>(&self) -> Result<SgxTrustedTlsChannel<U, V>>
-    where
-        U: Serialize + std::fmt::Debug,
-        V: for<'de> Deserialize<'de> + std::fmt::Debug,
-    {
-        SgxTrustedTlsChannel::<U, V>::new(&self.url, &self.config)
-    }
-
-    pub fn config(self, config: SgxTrustedTlsClientConfig) -> Self {
-        Self {
-            url: self.url,
-            config,
-        }
-    }
-}
diff --git a/rpc/src/interceptor.rs b/rpc/src/interceptor.rs
new file mode 100644
index 0000000..8367349
--- /dev/null
+++ b/rpc/src/interceptor.rs
@@ -0,0 +1,61 @@
+// 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 teaclave_types::UserRole;
+use tonic::{
+    codegen::InterceptedService, service::Interceptor, transport::Channel, IntoRequest, Request,
+    Status,
+};
+
+pub type CredentialService = InterceptedService<Channel, UserCredential>;
+
+// To verify authentication credentials of the request.
+#[derive(Debug, Default, Clone)]
+pub struct UserCredential {
+    pub id: String,
+    pub token: String,
+    pub role: UserRole,
+}
+
+impl Interceptor for UserCredential {
+    fn call(&mut self, request: Request<()>) -> Result<Request<()>, Status> {
+        let mut req = request.into_request();
+        let meta = req.metadata_mut();
+        meta.insert("id", self.id.parse().unwrap());
+        meta.insert("token", self.token.parse().unwrap());
+        meta.insert("role", self.role.to_string().parse().unwrap());
+        Ok(req)
+    }
+}
+
+impl UserCredential {
+    pub fn new(id: impl ToString, token: impl ToString) -> Self {
+        Self {
+            id: id.to_string(),
+            token: token.to_string(),
+            role: UserRole::default(),
+        }
+    }
+
+    pub fn with_role(id: impl ToString, token: impl ToString, role: UserRole) -> Self {
+        Self {
+            id: id.to_string(),
+            token: token.to_string(),
+            role,
+        }
+    }
+}
diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs
index 69cbc3f..84ef1c8 100644
--- a/rpc/src/lib.rs
+++ b/rpc/src/lib.rs
@@ -15,30 +15,16 @@
 // specific language governing permissions and limitations
 // under the License.
 
-#[cfg(feature = "mesalock_sgx")]
-extern crate sgx_trts;
-
-use serde::{Deserialize, Serialize};
-use teaclave_types::TeaclaveServiceResponseError;
-
-pub trait TeaclaveService<V, U>
-where
-    U: Serialize + std::fmt::Debug,
-    V: for<'de> Deserialize<'de> + std::fmt::Debug,
-{
-    fn handle_request(
-        &self,
-        request: Request<V>,
-    ) -> std::result::Result<U, TeaclaveServiceResponseError>;
-}
-
-pub mod channel;
 pub mod config;
-pub mod endpoint;
-mod protocol;
-mod request;
-pub use request::{IntoRequest, Request};
-pub use teaclave_rpc_proc_macro::into_request;
-#[cfg(any(feature = "mesalock_sgx", feature = "app"))]
-pub mod server;
-mod transport;
+pub mod interceptor;
+mod macros;
+
+pub use interceptor::{CredentialService, UserCredential};
+
+pub use tonic::{
+    async_trait, metadata::MetadataMap, service::interceptor::InterceptedService, Code,
+    IntoRequest, Request, Response, Status,
+};
+pub mod transport {
+    pub use tonic::transport::*;
+}
diff --git a/rpc/src/utils.rs b/rpc/src/macros.rs
similarity index 69%
rename from rpc/src/utils.rs
rename to rpc/src/macros.rs
index 39f8d90..f192eea 100644
--- a/rpc/src/utils.rs
+++ b/rpc/src/macros.rs
@@ -15,12 +15,17 @@
 // specific language governing permissions and limitations
 // under the License.
 
-#[allow(dead_code)]
-#[cfg(feature = "mesalock_sgx")]
-pub(crate) fn get_tcs_num() -> usize {
-    if sgx_trts::enclave::rsgx_is_supported_EDMM() {
-        sgx_trts::enclave::SgxGlobalData::new().get_dyn_tcs_num() as usize
-    } else {
-        (sgx_trts::enclave::SgxGlobalData::new().get_tcs_max_num() - 1) as usize
-    }
+#[macro_export]
+macro_rules! ensure {
+    ($cond:expr,$err:expr $(,)?) => {
+        if !$cond {
+            return std::result::Result::Err($err.into());
+        }
+    };
+
+    ($cond:expr,$code:expr,$err:expr $(,)?) => {
+        if !$cond {
+            return std::result::Result::Err($crate::Status::new($code, $err.to_string()));
+        }
+    };
 }
diff --git a/rpc/src/protocol.rs b/rpc/src/protocol.rs
deleted file mode 100644
index af2f09c..0000000
--- a/rpc/src/protocol.rs
+++ /dev/null
@@ -1,139 +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.
-
-#![allow(clippy::nonstandard_macro_braces)]
-
-use log::trace;
-use serde::{Deserialize, Serialize};
-use std::io;
-use std::vec::Vec;
-use teaclave_types::TeaclaveServiceResponseError;
-use thiserror::Error;
-
-#[derive(Error, Debug)]
-pub enum ProtocolError {
-    #[error("IoError")]
-    IoError(#[from] io::Error),
-    #[error("SerdeError")]
-    SerdeError(#[from] serde_json::error::Error),
-    #[error(transparent)]
-    Other(#[from] anyhow::Error),
-}
-
-impl From<ProtocolError> for TeaclaveServiceResponseError {
-    fn from(error: ProtocolError) -> Self {
-        match error {
-            ProtocolError::IoError(e) => {
-                TeaclaveServiceResponseError::ConnectionError(format!("{}", e))
-            }
-            ProtocolError::SerdeError(_) => {
-                TeaclaveServiceResponseError::InternalError("serde".to_string())
-            }
-            ProtocolError::Other(_) => {
-                TeaclaveServiceResponseError::InternalError("internal".to_string())
-            }
-        }
-    }
-}
-
-pub(crate) struct JsonProtocol<'a, T>
-where
-    T: io::Read + io::Write,
-{
-    pub transport: &'a mut T,
-    max_frame_len: u64,
-}
-
-impl<'a, T> JsonProtocol<'a, T>
-where
-    T: io::Read + io::Write,
-{
-    pub fn new(transport: &'a mut T) -> JsonProtocol<'a, T> {
-        Self {
-            transport,
-            // Default max frame length is 32MB
-            max_frame_len: 32 * 1_024 * 1_024,
-        }
-    }
-
-    pub fn read_message<V>(&mut self) -> std::result::Result<V, ProtocolError>
-    where
-        V: for<'de> Deserialize<'de> + std::fmt::Debug,
-    {
-        let mut header = [0u8; 8];
-
-        self.transport.read_exact(&mut header)?;
-        let buf_len = u64::from_be_bytes(header);
-        if buf_len > self.max_frame_len {
-            return Err(ProtocolError::Other(anyhow::anyhow!(
-                "Exceed max frame length"
-            )));
-        }
-
-        let mut recv_buf: Vec<u8> = vec![0u8; buf_len as usize];
-        self.transport.read_exact(&mut recv_buf)?;
-
-        trace!("Recv: {}", std::string::String::from_utf8_lossy(&recv_buf));
-        let r: V = serde_json::from_slice(&recv_buf)?;
-
-        Ok(r)
-    }
-
-    pub fn write_message<U>(&mut self, message: U) -> std::result::Result<(), ProtocolError>
-    where
-        U: Serialize + std::fmt::Debug,
-    {
-        let send_buf = serde_json::to_vec(&message)?;
-
-        trace!("Send: {}", std::string::String::from_utf8_lossy(&send_buf));
-
-        let buf_len = send_buf.len() as u64;
-        let header = buf_len.to_be_bytes();
-
-        self.transport.write_all(&header)?;
-        self.transport.write_all(&send_buf)?;
-        self.transport.flush()?;
-
-        Ok(())
-    }
-}
-
-#[derive(Debug, Serialize, Deserialize)]
-#[serde(tag = "result")]
-#[serde(rename_all = "snake_case")]
-pub enum JsonProtocolResult<T, E> {
-    Ok(T),
-    Err(E),
-}
-
-impl<T, E> From<std::result::Result<T, E>> for JsonProtocolResult<T, E> {
-    fn from(result: std::result::Result<T, E>) -> Self {
-        match result {
-            Ok(t) => JsonProtocolResult::Ok(t),
-            Err(e) => JsonProtocolResult::Err(e),
-        }
-    }
-}
-
-impl<T, E> From<JsonProtocolResult<T, E>> for std::result::Result<T, E> {
-    fn from(result: JsonProtocolResult<T, E>) -> Self {
-        match result {
-            JsonProtocolResult::Ok(t) => Ok(t),
-            JsonProtocolResult::Err(e) => Err(e),
-        }
-    }
-}
diff --git a/rpc/src/request.rs b/rpc/src/request.rs
deleted file mode 100644
index 026714c..0000000
--- a/rpc/src/request.rs
+++ /dev/null
@@ -1,66 +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 serde::{Deserialize, Serialize};
-use std::collections::HashMap;
-
-#[derive(Debug, Serialize, Deserialize, Clone)]
-pub struct Request<T> {
-    #[serde(skip_serializing_if = "HashMap::is_empty")]
-    #[serde(default)]
-    pub metadata: HashMap<String, String>,
-    pub message: T,
-}
-
-impl<T> Request<T> {
-    pub fn new(message: T) -> Self {
-        Request {
-            metadata: HashMap::<String, String>::default(),
-            message,
-        }
-    }
-
-    pub fn map<F, U>(self, f: F) -> Request<U>
-    where
-        F: FnOnce(T) -> U,
-    {
-        let message = f(self.message);
-
-        Request {
-            metadata: self.metadata,
-            message,
-        }
-    }
-
-    pub fn metadata(&self) -> &HashMap<String, String> {
-        &self.metadata
-    }
-
-    pub fn metadata_mut(&mut self) -> &mut HashMap<String, String> {
-        &mut self.metadata
-    }
-}
-
-pub trait IntoRequest<T> {
-    fn into_request(self) -> Request<T>;
-}
-
-impl<T> IntoRequest<T> for T {
-    fn into_request(self) -> Request<Self> {
-        Request::new(self)
-    }
-}
diff --git a/rpc/src/server.rs b/rpc/src/server.rs
deleted file mode 100644
index 27c3fc7..0000000
--- a/rpc/src/server.rs
+++ /dev/null
@@ -1,129 +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 crate::config::SgxTrustedTlsServerConfig;
-use crate::transport::{ServerTransport, SgxTrustedTlsTransport};
-use crate::TeaclaveService;
-use anyhow::Result;
-#[cfg(not(feature = "mesalock_sgx"))]
-use libc::setsockopt;
-use log::{debug, error, warn};
-use serde::{Deserialize, Serialize};
-#[cfg(feature = "mesalock_sgx")]
-use sgx_libc as libc;
-#[cfg(feature = "mesalock_sgx")]
-use sgx_libc::ocall::setsockopt;
-use std::{io, mem, os::unix::io::AsRawFd};
-
-pub struct SgxTrustedTlsServer<U, V>
-where
-    U: Serialize + std::fmt::Debug,
-    V: for<'de> Deserialize<'de> + std::fmt::Debug,
-{
-    addr: std::net::SocketAddr,
-    tls_config: SgxTrustedTlsServerConfig,
-    tcp_nodelay: bool,
-    n_workers: usize,
-    maker: std::marker::PhantomData<(U, V)>,
-}
-
-impl<U, V> SgxTrustedTlsServer<U, V>
-where
-    U: Serialize + std::fmt::Debug,
-    V: for<'de> Deserialize<'de> + std::fmt::Debug,
-{
-    pub fn new(
-        addr: std::net::SocketAddr,
-        server_config: SgxTrustedTlsServerConfig,
-    ) -> SgxTrustedTlsServer<U, V> {
-        Self {
-            addr,
-            tls_config: server_config,
-            tcp_nodelay: true,
-            n_workers: 8,
-            maker: std::marker::PhantomData::<(U, V)>,
-        }
-    }
-
-    pub fn tcp_nodelay(self, enabled: bool) -> Self {
-        Self {
-            tcp_nodelay: enabled,
-            ..self
-        }
-    }
-
-    pub fn n_workers(self, n: usize) -> Self {
-        Self {
-            n_workers: n,
-            ..self
-        }
-    }
-
-    pub fn start<X>(&mut self, service: X) -> Result<()>
-    where
-        X: 'static + TeaclaveService<V, U> + Clone + core::marker::Send,
-    {
-        let pool = threadpool::ThreadPool::new(self.n_workers);
-        let listener = std::net::TcpListener::bind(self.addr)?;
-        unsafe {
-            let optval: libc::c_int = 1;
-            let ret = setsockopt(
-                listener.as_raw_fd(),
-                libc::SOL_SOCKET,
-                libc::SO_REUSEPORT,
-                &optval as *const _ as *const libc::c_void,
-                mem::size_of_val(&optval) as libc::socklen_t,
-            );
-            if ret != 0 {
-                return Err(io::Error::last_os_error().into());
-            }
-        }
-        let mut tls_config_ref = self.tls_config.server_config();
-        for stream in listener.incoming() {
-            match stream {
-                Ok(stream) => {
-                    // Before introducing async into enclave, we check
-                    // freshness for every incoming connection.
-                    if self.tls_config.need_refresh() {
-                        debug!("Attestation report is outdated, need to refresh");
-                        self.tls_config.refresh_server_config()?;
-                        tls_config_ref = self.tls_config.server_config();
-                    }
-
-                    if let Err(e) = stream.set_nodelay(self.tcp_nodelay) {
-                        warn!("Cannot set_nodelay: {:}", e);
-                        continue;
-                    }
-                    let session = rustls::ServerSession::new(&tls_config_ref);
-                    let tls_stream = rustls::StreamOwned::new(session, stream);
-                    let mut transport = SgxTrustedTlsTransport::new(tls_stream);
-                    let service = service.clone();
-                    pool.execute(move || match transport.serve(service) {
-                        Ok(_) => (),
-                        Err(e) => {
-                            debug!("serve error: {:?}", e);
-                        }
-                    });
-                }
-                Err(e) => {
-                    error!("Incoming error: {:}", e);
-                }
-            }
-        }
-        Ok(())
-    }
-}
diff --git a/rpc/src/transport.rs b/rpc/src/transport.rs
deleted file mode 100644
index 9cea713..0000000
--- a/rpc/src/transport.rs
+++ /dev/null
@@ -1,119 +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 crate::protocol;
-use crate::Request;
-use crate::TeaclaveService;
-use anyhow::Result;
-use log::warn;
-use serde::{Deserialize, Serialize};
-
-pub(crate) trait ClientTransport {
-    fn send<U, V>(
-        &mut self,
-        request: Request<U>,
-    ) -> teaclave_types::TeaclaveServiceResponseResult<V>
-    where
-        U: Serialize + std::fmt::Debug,
-        V: for<'de> Deserialize<'de> + std::fmt::Debug;
-}
-
-pub(crate) trait ServerTransport {
-    fn serve<U, V, X>(&mut self, service: X) -> Result<()>
-    where
-        U: Serialize + std::fmt::Debug,
-        V: for<'de> Deserialize<'de> + std::fmt::Debug,
-        X: TeaclaveService<V, U>;
-}
-pub(crate) struct SgxTrustedTlsTransport<S>
-where
-    S: rustls::Session,
-{
-    stream: rustls::StreamOwned<S, std::net::TcpStream>,
-}
-
-impl<S> SgxTrustedTlsTransport<S>
-where
-    S: rustls::Session,
-{
-    pub fn new(stream: rustls::StreamOwned<S, std::net::TcpStream>) -> SgxTrustedTlsTransport<S> {
-        SgxTrustedTlsTransport::<S> { stream }
-    }
-}
-
-impl<S> ClientTransport for SgxTrustedTlsTransport<S>
-where
-    S: rustls::Session,
-{
-    fn send<U, V>(
-        &mut self,
-        request: Request<U>,
-    ) -> teaclave_types::TeaclaveServiceResponseResult<V>
-    where
-        U: Serialize + std::fmt::Debug,
-        V: for<'de> Deserialize<'de> + std::fmt::Debug,
-    {
-        let mut protocol = protocol::JsonProtocol::new(&mut self.stream);
-        protocol.write_message(request)?;
-        protocol.read_message::<protocol::JsonProtocolResult<
-                V,
-                teaclave_types::TeaclaveServiceResponseError,
-            >>()?
-            .into()
-    }
-}
-
-impl<S> ServerTransport for SgxTrustedTlsTransport<S>
-where
-    S: rustls::Session,
-{
-    fn serve<U, V, X>(&mut self, service: X) -> Result<()>
-    where
-        U: Serialize + std::fmt::Debug,
-        V: for<'de> Deserialize<'de> + std::fmt::Debug,
-        X: TeaclaveService<V, U>,
-    {
-        use crate::protocol::{JsonProtocol, JsonProtocolResult};
-        use teaclave_types::TeaclaveServiceResponseError;
-        let mut protocol = JsonProtocol::new(&mut self.stream);
-
-        loop {
-            let request: Request<V> = match protocol.read_message::<Request<V>>() {
-                Ok(r) => r,
-                Err(e) => match e {
-                    protocol::ProtocolError::IoError(e) => {
-                        log::debug!("Connection disconnected: {:?}", e);
-                        return Ok(());
-                    }
-                    _ => {
-                        warn!("Connection error: {:?}", e);
-                        let response: JsonProtocolResult<U, TeaclaveServiceResponseError> =
-                            Err(TeaclaveServiceResponseError::RequestError(
-                                "invalid request".to_string(),
-                            ))
-                            .into();
-                        protocol.write_message(response)?;
-                        return Ok(());
-                    }
-                },
-            };
-            let response: JsonProtocolResult<U, TeaclaveServiceResponseError> =
-                service.handle_request(request).into();
-            protocol.write_message(response)?;
-        }
-    }
-}
diff --git a/sdk/rust/Cargo.lock b/sdk/rust/Cargo.lock
index 4ee93bf..554cc4e 100644
--- a/sdk/rust/Cargo.lock
+++ b/sdk/rust/Cargo.lock
@@ -3,6 +3,12 @@
 version = 3
 
 [[package]]
+name = "adler"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
+
+[[package]]
 name = "aho-corasick"
 version = "0.7.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -18,6 +24,39 @@
 checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6"
 
 [[package]]
+name = "async-stream"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ad445822218ce64be7a341abfb0b1ea43b5c23aa83902542a4542e78309d8e5e"
+dependencies = [
+ "async-stream-impl",
+ "futures-core",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "async-stream-impl"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e4655ae1a7b0cdf149156f780c5bf3f1352bc53cbd9e0a361a7ef7b22947e965"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.105",
+]
+
+[[package]]
+name = "async-trait"
+version = "0.1.68"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.11",
+]
+
+[[package]]
 name = "autocfg"
 version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -42,10 +81,16 @@
 checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
 
 [[package]]
-name = "bumpalo"
-version = "3.11.1"
+name = "bitflags"
+version = "1.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "bumpalo"
+version = "3.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535"
 
 [[package]]
 name = "bytes"
@@ -82,12 +127,67 @@
 ]
 
 [[package]]
+name = "crc32fast"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
+dependencies = [
+ "cfg-if 1.0.0",
+]
+
+[[package]]
 name = "either"
 version = "1.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
 
 [[package]]
+name = "errno"
+version = "0.2.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1"
+dependencies = [
+ "errno-dragonfly",
+ "libc",
+ "winapi",
+]
+
+[[package]]
+name = "errno-dragonfly"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
+dependencies = [
+ "cc",
+ "libc",
+]
+
+[[package]]
+name = "fastrand"
+version = "1.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be"
+dependencies = [
+ "instant",
+]
+
+[[package]]
+name = "fixedbitset"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
+
+[[package]]
+name = "flate2"
+version = "1.0.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841"
+dependencies = [
+ "crc32fast",
+ "miniz_oxide",
+]
+
+[[package]]
 name = "fnv"
 version = "1.0.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -103,6 +203,45 @@
 ]
 
 [[package]]
+name = "futures-channel"
+version = "0.3.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "164713a5a0dcc3e7b4b1ed7d3b433cabc18025386f9339346e8daf15963cf7ac"
+dependencies = [
+ "futures-core",
+]
+
+[[package]]
+name = "futures-core"
+version = "0.3.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "86d7a0c1aa76363dac491de0ee99faf6941128376f1cf96f07db7603b7de69dd"
+
+[[package]]
+name = "futures-sink"
+version = "0.3.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec93083a4aecafb2a80a885c9de1f0ccae9dbd32c2bb54b0c3a65690e0b8d2f2"
+
+[[package]]
+name = "futures-task"
+version = "0.3.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd65540d33b37b16542a0438c12e6aeead10d4ac5d05bd3f805b8f35ab592879"
+
+[[package]]
+name = "futures-util"
+version = "0.3.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3ef6b17e481503ec85211fed8f39d1970f128935ca1f814cd32ac4a6842e84ab"
+dependencies = [
+ "futures-core",
+ "futures-task",
+ "pin-project-lite",
+ "pin-utils",
+]
+
+[[package]]
 name = "getrandom"
 version = "0.2.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -114,6 +253,40 @@
 ]
 
 [[package]]
+name = "h2"
+version = "0.3.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5be7b54589b581f624f566bf5d8eb2bab1db736c51528720b6bd36b96b55924d"
+dependencies = [
+ "bytes",
+ "fnv",
+ "futures-core",
+ "futures-sink",
+ "futures-util",
+ "http",
+ "indexmap",
+ "slab",
+ "tokio",
+ "tokio-util 0.7.7",
+ "tracing",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
+
+[[package]]
+name = "heck"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
+dependencies = [
+ "unicode-segmentation",
+]
+
+[[package]]
 name = "hermit-abi"
 version = "0.1.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -123,6 +296,12 @@
 ]
 
 [[package]]
+name = "hermit-abi"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
+
+[[package]]
 name = "hex"
 version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -140,12 +319,65 @@
 ]
 
 [[package]]
+name = "http-body"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1"
+dependencies = [
+ "bytes",
+ "http",
+ "pin-project-lite",
+]
+
+[[package]]
 name = "httparse"
 version = "1.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
 
 [[package]]
+name = "httpdate"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
+
+[[package]]
+name = "hyper"
+version = "0.14.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cc5e554ff619822309ffd57d8734d77cd5ce6238bc956f037ea06c58238c9899"
+dependencies = [
+ "bytes",
+ "futures-channel",
+ "futures-core",
+ "futures-util",
+ "h2",
+ "http",
+ "http-body",
+ "httparse",
+ "httpdate",
+ "itoa",
+ "pin-project-lite",
+ "socket2",
+ "tokio",
+ "tower-service",
+ "tracing",
+ "want",
+]
+
+[[package]]
+name = "hyper-timeout"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1"
+dependencies = [
+ "hyper",
+ "pin-project-lite",
+ "tokio",
+ "tokio-io-timeout",
+]
+
+[[package]]
 name = "idna"
 version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -156,6 +388,36 @@
 ]
 
 [[package]]
+name = "indexmap"
+version = "1.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
+dependencies = [
+ "autocfg",
+ "hashbrown",
+]
+
+[[package]]
+name = "instant"
+version = "0.1.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
+dependencies = [
+ "cfg-if 1.0.0",
+]
+
+[[package]]
+name = "io-lifetimes"
+version = "1.0.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09270fd4fa1111bc614ed2246c7ef56239a3063d5be0d1ec3b589c505d400aeb"
+dependencies = [
+ "hermit-abi 0.3.1",
+ "libc",
+ "windows-sys 0.45.0",
+]
+
+[[package]]
 name = "itertools"
 version = "0.10.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -187,9 +449,15 @@
 
 [[package]]
 name = "libc"
-version = "0.2.138"
+version = "0.2.140"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
+checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
+
+[[package]]
+name = "linux-raw-sys"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
 
 [[package]]
 name = "log"
@@ -207,6 +475,33 @@
 checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
 
 [[package]]
+name = "miniz_oxide"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
+dependencies = [
+ "adler",
+]
+
+[[package]]
+name = "mio"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9"
+dependencies = [
+ "libc",
+ "log",
+ "wasi",
+ "windows-sys 0.45.0",
+]
+
+[[package]]
+name = "multimap"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a"
+
+[[package]]
 name = "num-bigint"
 version = "0.2.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -242,7 +537,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5"
 dependencies = [
- "hermit-abi",
+ "hermit-abi 0.1.19",
  "libc",
 ]
 
@@ -270,6 +565,48 @@
 checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
 
 [[package]]
+name = "petgraph"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4"
+dependencies = [
+ "fixedbitset",
+ "indexmap",
+]
+
+[[package]]
+name = "pin-project"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc"
+dependencies = [
+ "pin-project-internal",
+]
+
+[[package]]
+name = "pin-project-internal"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.105",
+]
+
+[[package]]
+name = "pin-project-lite"
+version = "0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
+
+[[package]]
+name = "pin-utils"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
+
+[[package]]
 name = "ppv-lite86"
 version = "0.2.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -277,41 +614,71 @@
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.47"
+version = "1.0.54"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
+checksum = "e472a104799c74b514a57226160104aa483546de37e839ec50e3c2e41dd87534"
 dependencies = [
  "unicode-ident",
 ]
 
 [[package]]
 name = "prost"
-version = "0.11.8"
+version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e48e50df39172a3e7eb17e14642445da64996989bc212b583015435d39a58537"
+checksum = "444879275cb4fd84958b1a1d5420d15e6fcf7c235fe47f053c9c2a80aceb6001"
 dependencies = [
  "bytes",
  "prost-derive",
 ]
 
 [[package]]
-name = "prost-derive"
-version = "0.11.8"
+name = "prost-build"
+version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ea9b0f8cbe5e15a8a042d030bd96668db28ecb567ec37d691971ff5731d2b1b"
+checksum = "62941722fb675d463659e49c4f3fe1fe792ff24fe5bbaa9c08cd3b98a1c354f5"
+dependencies = [
+ "bytes",
+ "heck",
+ "itertools",
+ "lazy_static",
+ "log",
+ "multimap",
+ "petgraph",
+ "prost",
+ "prost-types",
+ "regex",
+ "tempfile",
+ "which",
+]
+
+[[package]]
+name = "prost-derive"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f9cc1a3263e07e0bf68e96268f37665207b49560d98739662cdfaae215c720fe"
 dependencies = [
  "anyhow",
  "itertools",
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.105",
+]
+
+[[package]]
+name = "prost-types"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "534b7a0e836e3c482d2693070f982e39e7611da9695d4d1f5a4b186b51faef0a"
+dependencies = [
+ "bytes",
+ "prost",
 ]
 
 [[package]]
 name = "quote"
-version = "1.0.21"
+version = "1.0.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
+checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
 dependencies = [
  "proc-macro2",
 ]
@@ -356,6 +723,15 @@
 ]
 
 [[package]]
+name = "redox_syscall"
+version = "0.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
 name = "regex"
 version = "1.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -388,12 +764,26 @@
 ]
 
 [[package]]
-name = "rustls"
-version = "0.17.0"
+name = "rustix"
+version = "0.36.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0d4a31f5d68413404705d6982529b0e11a9aacd4839d1d6222ee3b8cb4015e1"
+checksum = "db4165c9963ab29e422d6c26fbc1d37f15bace6b2810221f9d925023480fcf0e"
 dependencies = [
- "base64 0.11.0",
+ "bitflags",
+ "errno",
+ "io-lifetimes",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys 0.45.0",
+]
+
+[[package]]
+name = "rustls"
+version = "0.19.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "35edb675feee39aec9c99fa5ff985081995a06d594114ae14cbe797ad7b7a6d7"
+dependencies = [
+ "base64 0.13.1",
  "log",
  "ring",
  "sct",
@@ -433,7 +823,7 @@
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.105",
 ]
 
 [[package]]
@@ -522,6 +912,25 @@
 checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012"
 
 [[package]]
+name = "slab"
+version = "0.4.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "socket2"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662"
+dependencies = [
+ "libc",
+ "winapi",
+]
+
+[[package]]
 name = "spin"
 version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -539,6 +948,17 @@
 ]
 
 [[package]]
+name = "syn"
+version = "2.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "21e3787bb71465627110e7d87ed4faaa36c1f61042ee67badb9e2ef173accc40"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
 name = "teaclave_attestation"
 version = "0.5.1"
 dependencies = [
@@ -579,6 +999,7 @@
  "teaclave_proto",
  "teaclave_rpc",
  "teaclave_types",
+ "tokio",
  "url",
 ]
 
@@ -611,16 +1032,14 @@
 version = "0.5.1"
 dependencies = [
  "anyhow",
- "base64 0.13.1",
- "cfg-if 0.1.10",
  "prost",
- "rand",
  "serde",
  "serde_json",
  "sgx_types",
  "teaclave_crypto",
- "teaclave_rpc",
  "teaclave_types",
+ "tonic",
+ "tonic-build",
  "url",
  "uuid",
 ]
@@ -630,30 +1049,15 @@
 version = "0.5.1"
 dependencies = [
  "anyhow",
- "cfg-if 0.1.10",
- "http",
  "log",
  "rustls",
- "serde",
- "serde_json",
  "teaclave_attestation",
- "teaclave_rpc_proc_macro",
  "teaclave_types",
- "thiserror",
- "threadpool",
+ "tonic",
  "webpki",
 ]
 
 [[package]]
-name = "teaclave_rpc_proc_macro"
-version = "0.5.1"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
 name = "teaclave_types"
 version = "0.5.1"
 dependencies = [
@@ -669,11 +1073,25 @@
  "teaclave_crypto",
  "thiserror",
  "toml",
+ "tonic",
  "url",
  "uuid",
 ]
 
 [[package]]
+name = "tempfile"
+version = "3.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af18f7ae1acd354b992402e9ec5864359d693cd8a79dcbef59f76891701c1e95"
+dependencies = [
+ "cfg-if 1.0.0",
+ "fastrand",
+ "redox_syscall",
+ "rustix",
+ "windows-sys 0.42.0",
+]
+
+[[package]]
 name = "thiserror"
 version = "1.0.37"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -690,16 +1108,7 @@
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
-]
-
-[[package]]
-name = "threadpool"
-version = "1.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa"
-dependencies = [
- "num_cpus",
+ "syn 1.0.105",
 ]
 
 [[package]]
@@ -718,6 +1127,94 @@
 checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
 
 [[package]]
+name = "tokio"
+version = "1.27.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d0de47a4eecbe11f498978a9b29d792f0d2692d1dd003650c24c76510e3bc001"
+dependencies = [
+ "autocfg",
+ "bytes",
+ "libc",
+ "mio",
+ "num_cpus",
+ "pin-project-lite",
+ "socket2",
+ "tokio-macros",
+ "windows-sys 0.45.0",
+]
+
+[[package]]
+name = "tokio-io-timeout"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf"
+dependencies = [
+ "pin-project-lite",
+ "tokio",
+]
+
+[[package]]
+name = "tokio-macros"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "61a573bdc87985e9d6ddeed1b3d864e8a302c847e40d647746df2f1de209d1ce"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.11",
+]
+
+[[package]]
+name = "tokio-rustls"
+version = "0.22.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6"
+dependencies = [
+ "rustls",
+ "tokio",
+ "webpki",
+]
+
+[[package]]
+name = "tokio-stream"
+version = "0.1.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8fb52b74f05dbf495a8fba459fdc331812b96aa086d9eb78101fa0d4569c3313"
+dependencies = [
+ "futures-core",
+ "pin-project-lite",
+ "tokio",
+]
+
+[[package]]
+name = "tokio-util"
+version = "0.6.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507"
+dependencies = [
+ "bytes",
+ "futures-core",
+ "futures-sink",
+ "log",
+ "pin-project-lite",
+ "tokio",
+]
+
+[[package]]
+name = "tokio-util"
+version = "0.7.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2"
+dependencies = [
+ "bytes",
+ "futures-core",
+ "futures-sink",
+ "pin-project-lite",
+ "tokio",
+ "tracing",
+]
+
+[[package]]
 name = "toml"
 version = "0.5.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -727,6 +1224,132 @@
 ]
 
 [[package]]
+name = "tonic"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ff08f4649d10a70ffa3522ca559031285d8e421d727ac85c60825761818f5d0a"
+dependencies = [
+ "async-stream",
+ "async-trait",
+ "base64 0.13.1",
+ "bytes",
+ "flate2",
+ "futures-core",
+ "futures-util",
+ "h2",
+ "http",
+ "http-body",
+ "hyper",
+ "hyper-timeout",
+ "percent-encoding",
+ "pin-project",
+ "prost",
+ "prost-derive",
+ "tokio",
+ "tokio-rustls",
+ "tokio-stream",
+ "tokio-util 0.6.10",
+ "tower",
+ "tower-layer",
+ "tower-service",
+ "tracing",
+ "tracing-futures",
+]
+
+[[package]]
+name = "tonic-build"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9403f1bafde247186684b230dc6f38b5cd514584e8bec1dd32514be4745fa757"
+dependencies = [
+ "proc-macro2",
+ "prost-build",
+ "quote",
+ "syn 1.0.105",
+]
+
+[[package]]
+name = "tower"
+version = "0.4.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
+dependencies = [
+ "futures-core",
+ "futures-util",
+ "indexmap",
+ "pin-project",
+ "pin-project-lite",
+ "rand",
+ "slab",
+ "tokio",
+ "tokio-util 0.7.7",
+ "tower-layer",
+ "tower-service",
+ "tracing",
+]
+
+[[package]]
+name = "tower-layer"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0"
+
+[[package]]
+name = "tower-service"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
+
+[[package]]
+name = "tracing"
+version = "0.1.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
+dependencies = [
+ "cfg-if 1.0.0",
+ "log",
+ "pin-project-lite",
+ "tracing-attributes",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-attributes"
+version = "0.1.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.105",
+]
+
+[[package]]
+name = "tracing-core"
+version = "0.1.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a"
+dependencies = [
+ "once_cell",
+]
+
+[[package]]
+name = "tracing-futures"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2"
+dependencies = [
+ "pin-project",
+ "tracing",
+]
+
+[[package]]
+name = "try-lock"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
+
+[[package]]
 name = "unicode-bidi"
 version = "0.3.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -748,6 +1371,12 @@
 ]
 
 [[package]]
+name = "unicode-segmentation"
+version = "1.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36"
+
+[[package]]
 name = "untrusted"
 version = "0.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -777,6 +1406,16 @@
 ]
 
 [[package]]
+name = "want"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0"
+dependencies = [
+ "log",
+ "try-lock",
+]
+
+[[package]]
 name = "wasi"
 version = "0.11.0+wasi-snapshot-preview1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -803,7 +1442,7 @@
  "once_cell",
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.105",
  "wasm-bindgen-shared",
 ]
 
@@ -825,7 +1464,7 @@
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.105",
  "wasm-bindgen-backend",
  "wasm-bindgen-shared",
 ]
@@ -866,6 +1505,17 @@
 ]
 
 [[package]]
+name = "which"
+version = "4.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269"
+dependencies = [
+ "either",
+ "libc",
+ "once_cell",
+]
+
+[[package]]
 name = "winapi"
 version = "0.3.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -888,6 +1538,87 @@
 checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 
 [[package]]
+name = "windows-sys"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.45.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
+
+[[package]]
 name = "yasna"
 version = "0.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/sdk/rust/Cargo.toml b/sdk/rust/Cargo.toml
index eb9ffd2..5cf7a71 100644
--- a/sdk/rust/Cargo.toml
+++ b/sdk/rust/Cargo.toml
@@ -27,16 +27,17 @@
 crate-type = ["lib", "cdylib", "staticlib"]
 
 [dependencies]
-teaclave_types = { path = "../../types", features = ["app"] }
-teaclave_attestation = { path = "../../attestation" }
-teaclave_rpc = { path = "../../rpc" }
-teaclave_proto = { path = "../../services/proto" }
-anyhow       = { version = "1.0.26" }
-url          = { version = "2.1.1" }
-serde_json    = { version = "1.0.39" }
-serde         = { version = "1.0.92" }
-pem = "0.7.0"
-libc = "0.2.68"
+teaclave_types        = { path = "../../types", features = ["app"] }
+teaclave_attestation  = { path = "../../attestation" }
+teaclave_rpc          = { path = "../../rpc" }
+teaclave_proto        = { path = "../../services/proto" }
+anyhow                = { version = "1.0.26" }
+url                   = { version = "2.1.1" }
+serde_json            = { version = "1.0.39" }
+serde                 = { version = "1.0.92" }
+pem                   = { version = "0.7.0" }
+libc                  = { version = "0.2.68" }
+tokio                 = { version = "1.0", features = ["rt-multi-thread", "time", "macros"] }
 
 [patch.crates-io]
 sgx_tprotected_fs = { path = "../../third_party/rust-sgx-sdk/sgx_protected_fs/tfs" }
diff --git a/sdk/rust/src/lib.rs b/sdk/rust/src/lib.rs
index a212624..f015c67 100644
--- a/sdk/rust/src/lib.rs
+++ b/sdk/rust/src/lib.rs
@@ -15,20 +15,19 @@
 // specific language governing permissions and limitations
 // under the License.
 
-use anyhow::Result;
+use anyhow::{bail, Result};
 use std::collections::HashMap;
-use std::convert::TryInto;
+use std::convert::{TryFrom, TryInto};
 use teaclave_attestation::verifier;
 use teaclave_proto::teaclave_authentication_service::TeaclaveAuthenticationApiClient;
-use teaclave_proto::teaclave_authentication_service_proto as authentication_proto;
 use teaclave_proto::teaclave_frontend_service::TeaclaveFrontendClient;
-use teaclave_proto::teaclave_frontend_service_proto as frontend_proto;
-use teaclave_rpc::config::SgxTrustedTlsClientConfig;
-use teaclave_rpc::endpoint::Endpoint;
+use teaclave_rpc::transport::{Channel, Uri};
+use teaclave_rpc::{config::SgxTrustedTlsClientConfig, CredentialService, UserCredential};
 use teaclave_types::FileAuthTag;
+use tokio::runtime::Runtime;
 use url::Url;
 
-pub use teaclave_proto::teaclave_authentication_service::{
+use teaclave_proto::teaclave_authentication_service_proto::{
     UserLoginRequest, UserLoginResponse, UserRegisterRequest, UserRegisterResponse,
 };
 pub use teaclave_proto::teaclave_frontend_service::GetFunctionResponse as Function;
@@ -48,38 +47,49 @@
 
 pub mod bindings;
 
+// This macro is intended for use cases where you are invoking from synchronous code to asynchronous code.
+macro_rules! do_request_with_credential {
+    ($client:ident,$fun:ident,$request:ident) => {{
+        let response = $client.rt.block_on($client.client.$fun($request))?;
+        Ok(response.into_inner())
+    }};
+}
+
 pub struct AuthenticationClient {
-    api_client: TeaclaveAuthenticationApiClient,
+    client: TeaclaveAuthenticationApiClient<CredentialService>,
+    rt: Runtime,
+    channel: Channel,
 }
 
 pub struct AuthenticationService;
 
 impl AuthenticationClient {
-    pub fn new(api_client: TeaclaveAuthenticationApiClient) -> Self {
-        Self { api_client }
+    pub fn new(channel: Channel, rt: Runtime) -> Self {
+        Self {
+            client: TeaclaveAuthenticationApiClient::with_interceptor(
+                channel.clone(),
+                UserCredential::default(),
+            ),
+            channel,
+            rt,
+        }
     }
 
     pub fn set_credential(&mut self, id: &str, token: &str) {
-        let mut metadata = HashMap::new();
-        metadata.insert("id".to_string(), id.to_string());
-        metadata.insert("token".to_string(), token.to_string());
-        self.api_client.set_metadata(metadata);
+        let cred = UserCredential::new(id, token);
+        self.client = TeaclaveAuthenticationApiClient::with_interceptor(self.channel.clone(), cred);
     }
 
     pub fn user_register_with_request(
         &mut self,
         request: UserRegisterRequest,
     ) -> Result<UserRegisterResponse> {
-        let response = self.api_client.user_register(request)?;
-
-        Ok(response)
+        do_request_with_credential!(self, user_register, request)
     }
 
     pub fn user_register_serialized(&mut self, serialized_request: &str) -> Result<String> {
-        let request: authentication_proto::UserRegisterRequest =
-            serde_json::from_str(serialized_request)?;
-        let response: authentication_proto::UserRegisterResponse =
-            self.user_register_with_request(request.try_into()?)?.into();
+        let request = serde_json::from_str(serialized_request)?;
+        let response = self.user_register_with_request(request)?;
         let serialized_response = serde_json::to_string(&response)?;
 
         Ok(serialized_response)
@@ -102,16 +112,13 @@
         &mut self,
         request: UserLoginRequest,
     ) -> Result<UserLoginResponse> {
-        let response = self.api_client.user_login(request)?;
-
-        Ok(response)
+        let response = self.rt.block_on(self.client.user_login(request))?;
+        Ok(response.into_inner())
     }
 
     pub fn user_login_serialized(&mut self, serialized_request: &str) -> Result<String> {
-        let request: authentication_proto::UserLoginRequest =
-            serde_json::from_str(serialized_request)?;
-        let response: authentication_proto::UserLoginResponse =
-            self.user_login_with_request(request.try_into()?)?.into();
+        let request = serde_json::from_str(serialized_request)?;
+        let response = self.user_login_with_request(request)?;
         let serialized_response = serde_json::to_string(&response)?;
 
         Ok(serialized_response)
@@ -134,15 +141,31 @@
         let enclave_attr = enclave_info
             .get_enclave_attr("teaclave_authentication_service")
             .expect("enclave attr");
-        let config = SgxTrustedTlsClientConfig::new().attestation_report_verifier(
-            vec![enclave_attr],
-            as_root_ca_cert,
-            verifier::universal_quote_verifier,
-        );
-        let channel = Endpoint::new(url).config(config).connect()?;
-        let client = TeaclaveAuthenticationApiClient::new(channel)?;
-
-        Ok(AuthenticationClient::new(client))
+        let tls_config = SgxTrustedTlsClientConfig::new()
+            .attestation_report_verifier(
+                vec![enclave_attr],
+                as_root_ca_cert,
+                verifier::universal_quote_verifier,
+            )
+            .into();
+        let rt = tokio::runtime::Builder::new_current_thread()
+            .enable_all()
+            .build()
+            .unwrap();
+        let dst = url.parse::<Uri>()?;
+        if dst.scheme().is_none() {
+            bail!("Invaild Uri: no scheme");
+        }
+        let endpoint = Channel::builder(dst);
+        let client = rt.block_on(async {
+            endpoint
+                .tls_config(tls_config)
+                .unwrap()
+                .connect()
+                .await
+                .unwrap()
+        });
+        Ok(AuthenticationClient::new(client, rt))
     }
 }
 
@@ -158,40 +181,65 @@
         let enclave_attr = enclave_info
             .get_enclave_attr("teaclave_frontend_service")
             .expect("enclave attr");
-        let config = SgxTrustedTlsClientConfig::new().attestation_report_verifier(
-            vec![enclave_attr],
-            as_root_ca_cert,
-            verifier::universal_quote_verifier,
-        );
-        let channel = Endpoint::new(url).config(config).connect()?;
-        let client = TeaclaveFrontendClient::new(channel)?;
+        let tls_config = teaclave_rpc::config::SgxTrustedTlsClientConfig::new()
+            .attestation_report_verifier(
+                vec![enclave_attr],
+                as_root_ca_cert,
+                verifier::universal_quote_verifier,
+            )
+            .into();
 
-        Ok(FrontendClient::new(client))
+        let rt = tokio::runtime::Builder::new_current_thread()
+            .enable_all()
+            .build()
+            .unwrap();
+        let dst = url.parse::<Uri>()?;
+        if dst.scheme().is_none() {
+            bail!("Invaild Uri: no scheme");
+        }
+
+        let endpoint = Channel::builder(dst);
+        let client = rt.block_on(async {
+            let channel = endpoint
+                .tls_config(tls_config)
+                .unwrap()
+                .connect()
+                .await
+                .unwrap();
+            channel
+        });
+
+        Ok(FrontendClient::new(client, rt))
     }
 }
 
 pub struct FrontendClient {
-    api_client: TeaclaveFrontendClient,
+    client: TeaclaveFrontendClient<CredentialService>,
+    rt: Runtime,
+    channel: Channel,
 }
 
 impl FrontendClient {
-    pub fn new(api_client: TeaclaveFrontendClient) -> Self {
-        Self { api_client }
+    pub fn new(channel: Channel, rt: Runtime) -> Self {
+        Self {
+            client: TeaclaveFrontendClient::with_interceptor(
+                channel.clone(),
+                UserCredential::default(),
+            ),
+            channel,
+            rt,
+        }
     }
 
+    // The id in AuthenticationServiceRequest is the username.
     pub fn set_credential(&mut self, id: &str, token: &str) {
-        let mut metadata = HashMap::new();
-        metadata.insert("id".to_string(), id.to_string());
-        metadata.insert("token".to_string(), token.to_string());
-        self.api_client.set_metadata(metadata);
+        let cred = UserCredential::new(id, token);
+        self.client = TeaclaveFrontendClient::with_interceptor(self.channel.clone(), cred);
     }
 
     pub fn register_function_serialized(&mut self, serialized_request: &str) -> Result<String> {
-        let request: frontend_proto::RegisterFunctionRequest =
-            serde_json::from_str(serialized_request)?;
-        let response: frontend_proto::RegisterFunctionResponse = self
-            .register_function_with_request(request.try_into()?)?
-            .into();
+        let request = serde_json::from_str(serialized_request)?;
+        let response = self.register_function_with_request(request)?;
         let serialized_response = serde_json::to_string(&response)?;
 
         Ok(serialized_response)
@@ -201,9 +249,7 @@
         &mut self,
         request: RegisterFunctionRequest,
     ) -> Result<RegisterFunctionResponse> {
-        let response = self.api_client.register_function(request)?;
-
-        Ok(response)
+        do_request_with_credential!(self, register_function, request)
     }
 
     #[allow(clippy::too_many_arguments)]
@@ -244,22 +290,19 @@
         let request = builder.build();
         let response = self.register_function_with_request(request)?;
 
-        Ok(response.function_id.to_string())
+        Ok(response.function_id)
     }
 
     pub fn get_function_with_request(
         &mut self,
         request: GetFunctionRequest,
     ) -> Result<GetFunctionResponse> {
-        let response = self.api_client.get_function(request)?;
-
-        Ok(response)
+        do_request_with_credential!(self, get_function, request)
     }
 
     pub fn get_function_serialized(&mut self, serialized_request: &str) -> Result<String> {
-        let request: frontend_proto::GetFunctionRequest = serde_json::from_str(serialized_request)?;
-        let response: frontend_proto::GetFunctionResponse =
-            self.get_function_with_request(request.try_into()?)?.into();
+        let request = serde_json::from_str(serialized_request)?;
+        let response = self.get_function_with_request(request)?;
         let serialized_response = serde_json::to_string(&response)?;
 
         Ok(serialized_response)
@@ -277,11 +320,8 @@
         &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 request = serde_json::from_str(serialized_request)?;
+        let response = self.get_function_usage_stats_with_request(request)?;
         let serialized_response = serde_json::to_string(&response)?;
 
         Ok(serialized_response)
@@ -299,26 +339,19 @@
         &mut self,
         request: GetFunctionUsageStatsRequest,
     ) -> Result<GetFunctionUsageStatsResponse> {
-        let response = self.api_client.get_function_usage_stats(request)?;
-
-        Ok(response)
+        do_request_with_credential!(self, get_function_usage_stats, request)
     }
 
     pub fn register_input_file_with_request(
         &mut self,
         request: RegisterInputFileRequest,
     ) -> Result<RegisterInputFileResponse> {
-        let response = self.api_client.register_input_file(request)?;
-
-        Ok(response)
+        do_request_with_credential!(self, register_input_file, request)
     }
 
     pub fn register_input_file_serialized(&mut self, serialized_request: &str) -> Result<String> {
-        let request: frontend_proto::RegisterInputFileRequest =
-            serde_json::from_str(serialized_request)?;
-        let response: frontend_proto::RegisterInputFileResponse = self
-            .register_input_file_with_request(request.try_into()?)?
-            .into();
+        let request = serde_json::from_str(serialized_request)?;
+        let response = self.register_input_file_with_request(request)?;
         let serialized_response = serde_json::to_string(&response)?;
 
         Ok(serialized_response)
@@ -335,24 +368,19 @@
         let request = RegisterInputFileRequest::new(url, cmac, file_crypto);
         let response = self.register_input_file_with_request(request)?;
 
-        Ok(response.data_id.to_string())
+        Ok(response.data_id)
     }
 
     pub fn register_output_file_with_request(
         &mut self,
         request: RegisterOutputFileRequest,
     ) -> Result<RegisterOutputFileResponse> {
-        let response = self.api_client.register_output_file(request)?;
-
-        Ok(response)
+        do_request_with_credential!(self, register_output_file, request)
     }
 
     pub fn register_output_file_serialized(&mut self, serialized_request: &str) -> Result<String> {
-        let request: frontend_proto::RegisterOutputFileRequest =
-            serde_json::from_str(serialized_request)?;
-        let response: frontend_proto::RegisterOutputFileResponse = self
-            .register_output_file_with_request(request.try_into()?)?
-            .into();
+        let request = serde_json::from_str(serialized_request)?;
+        let response = self.register_output_file_with_request(request)?;
         let serialized_response = serde_json::to_string(&response)?;
 
         Ok(serialized_response)
@@ -363,13 +391,12 @@
         let request = RegisterOutputFileRequest::new(url, file_crypto);
         let response = self.register_output_file_with_request(request)?;
 
-        Ok(response.data_id.to_string())
+        Ok(response.data_id)
     }
 
     pub fn create_task_serialized(&mut self, serialized_request: &str) -> Result<String> {
-        let request: frontend_proto::CreateTaskRequest = serde_json::from_str(serialized_request)?;
-        let response: frontend_proto::CreateTaskResponse =
-            self.create_task_with_request(request.try_into()?)?.into();
+        let request = serde_json::from_str(serialized_request)?;
+        let response = self.create_task_with_request(request)?;
         let serialized_response = serde_json::to_string(&response)?;
 
         Ok(serialized_response)
@@ -379,9 +406,7 @@
         &mut self,
         request: CreateTaskRequest,
     ) -> Result<CreateTaskResponse> {
-        let response = self.api_client.create_task(request)?;
-
-        Ok(response)
+        do_request_with_credential!(self, create_task, request)
     }
 
     pub fn create_task(
@@ -422,22 +447,19 @@
 
         let response = self.create_task_with_request(request)?;
 
-        Ok(response.task_id.to_string())
+        Ok(response.task_id)
     }
 
     pub fn assign_data_with_request(
         &mut self,
         request: AssignDataRequest,
     ) -> Result<AssignDataResponse> {
-        let response = self.api_client.assign_data(request)?;
-
-        Ok(response)
+        do_request_with_credential!(self, assign_data, request)
     }
 
     pub fn assign_data_serialized(&mut self, serialized_request: &str) -> Result<String> {
-        let request: frontend_proto::AssignDataRequest = serde_json::from_str(serialized_request)?;
-        let response: frontend_proto::AssignDataResponse =
-            self.assign_data_with_request(request.try_into()?)?.into();
+        let request = serde_json::from_str(serialized_request)?;
+        let response = self.assign_data_with_request(request)?;
         let serialized_response = serde_json::to_string(&response)?;
 
         Ok(serialized_response)
@@ -472,9 +494,7 @@
         &mut self,
         request: ApproveTaskRequest,
     ) -> Result<ApproveTaskResponse> {
-        let response = self.api_client.approve_task(request)?;
-
-        Ok(response)
+        do_request_with_credential!(self, approve_task, request)
     }
 
     pub fn approve_task(&mut self, task_id: &str) -> Result<()> {
@@ -485,9 +505,8 @@
     }
 
     pub fn approve_task_serialized(&mut self, serialized_request: &str) -> Result<String> {
-        let request: frontend_proto::ApproveTaskRequest = serde_json::from_str(serialized_request)?;
-        let response: frontend_proto::ApproveTaskResponse =
-            self.approve_task_with_request(request.try_into()?)?.into();
+        let request = serde_json::from_str(serialized_request)?;
+        let response = self.approve_task_with_request(request)?;
         let serialized_response = serde_json::to_string(&response)?;
 
         Ok(serialized_response)
@@ -497,15 +516,12 @@
         &mut self,
         request: InvokeTaskRequest,
     ) -> Result<InvokeTaskResponse> {
-        let response = self.api_client.invoke_task(request)?;
-
-        Ok(response)
+        do_request_with_credential!(self, invoke_task, request)
     }
 
     pub fn invoke_task_serialized(&mut self, serialized_request: &str) -> Result<String> {
-        let request: frontend_proto::InvokeTaskRequest = serde_json::from_str(serialized_request)?;
-        let response: frontend_proto::InvokeTaskResponse =
-            self.invoke_task_with_request(request.try_into()?)?.into();
+        let request = serde_json::from_str(serialized_request)?;
+        let response = self.invoke_task_with_request(request)?;
         let serialized_response = serde_json::to_string(&response)?;
 
         Ok(serialized_response)
@@ -519,15 +535,12 @@
     }
 
     pub fn get_task_with_request(&mut self, request: GetTaskRequest) -> Result<GetTaskResponse> {
-        let response = self.api_client.get_task(request)?;
-
-        Ok(response)
+        do_request_with_credential!(self, get_task, request)
     }
 
     pub fn get_task_serialized(&mut self, serialized_request: &str) -> Result<String> {
-        let request: frontend_proto::GetTaskRequest = serde_json::from_str(serialized_request)?;
-        let response: frontend_proto::GetTaskResponse =
-            self.get_task_with_request(request.try_into()?)?.into();
+        let request = serde_json::from_str(serialized_request)?;
+        let response = self.get_task_with_request(request)?;
         let serialized_response = serde_json::to_string(&response)?;
 
         Ok(serialized_response)
@@ -537,7 +550,8 @@
         loop {
             let request = GetTaskRequest::new(task_id.try_into()?);
             let response = self.get_task_with_request(request)?;
-            match response.result {
+            let result = teaclave_types::TaskResult::try_from(response.result)?;
+            match result {
                 TaskResult::NotReady => {
                     std::thread::sleep(std::time::Duration::from_secs(1));
                 }
@@ -555,15 +569,12 @@
         &mut self,
         request: CancelTaskRequest,
     ) -> Result<CancelTaskResponse> {
-        let response = self.api_client.cancel_task(request)?;
-
-        Ok(response)
+        do_request_with_credential!(self, cancel_task, request)
     }
 
     pub fn cancel_task_serialized(&mut self, serialized_request: &str) -> Result<String> {
-        let request: frontend_proto::CancelTaskRequest = serde_json::from_str(serialized_request)?;
-        let response: frontend_proto::CancelTaskResponse =
-            self.cancel_task_with_request(request.try_into()?)?.into();
+        let request = serde_json::from_str(serialized_request)?;
+        let response = self.cancel_task_with_request(request)?;
         let serialized_response = serde_json::to_string(&response)?;
 
         Ok(serialized_response)
@@ -594,36 +605,35 @@
     const ADMIN_ID: &str = "admin";
     const ADMIN_PASSWORD: &str = "teaclave";
 
-    #[test]
-    fn test_authentication_service() {
+    fn get_frontend_client() -> FrontendClient {
         let enclave_info = EnclaveInfo::from_file(ENCLAVE_INFO_PATH).unwrap();
         let bytes = fs::read(AS_ROOT_CA_CERT_PATH).unwrap();
         let as_root_ca_cert = pem::parse(bytes).unwrap().contents;
-        let mut client =
-            AuthenticationService::connect("localhost:7776", &enclave_info, &as_root_ca_cert)
-                .unwrap();
-        let token = client.user_login(ADMIN_ID, ADMIN_PASSWORD).unwrap();
-        client.set_credential(ADMIN_ID, &token);
-        let _ = client.user_register(USER_ID, USER_PASSWORD, "PlatformAdmin", "");
-        client.user_login(USER_ID, USER_PASSWORD).unwrap();
-    }
-
-    #[test]
-    fn test_frontend_service() {
-        let enclave_info = EnclaveInfo::from_file(ENCLAVE_INFO_PATH).unwrap();
-        let bytes = fs::read(AS_ROOT_CA_CERT_PATH).unwrap();
-        let as_root_ca_cert = pem::parse(bytes).unwrap().contents;
-        let mut client =
-            AuthenticationService::connect("localhost:7776", &enclave_info, &as_root_ca_cert)
-                .unwrap();
+        let mut client = AuthenticationService::connect(
+            "https://localhost:7776",
+            &enclave_info,
+            &as_root_ca_cert,
+        )
+        .unwrap();
         let token = client.user_login(ADMIN_ID, ADMIN_PASSWORD).unwrap();
         client.set_credential(ADMIN_ID, &token);
         let _ = client.user_register(USER_ID, USER_PASSWORD, "PlatformAdmin", "");
         let token = client.user_login(USER_ID, USER_PASSWORD).unwrap();
-
         let mut client =
-            FrontendService::connect("localhost:7777", &enclave_info, &as_root_ca_cert).unwrap();
+            FrontendService::connect("https://localhost:7777", &enclave_info, &as_root_ca_cert)
+                .unwrap();
         client.set_credential(USER_ID, &token);
+        client
+    }
+
+    #[test]
+    fn test_authentication_service() {
+        get_frontend_client();
+    }
+
+    #[test]
+    fn test_frontend_service() {
+        let mut client = get_frontend_client();
         let function_id = client
             .register_function(
                 "builtin-echo",
@@ -685,27 +695,14 @@
 
     #[test]
     fn test_frontend_service_with_request() {
-        let enclave_info = EnclaveInfo::from_file(ENCLAVE_INFO_PATH).unwrap();
-        let bytes = fs::read(AS_ROOT_CA_CERT_PATH).unwrap();
-        let as_root_ca_cert = pem::parse(bytes).unwrap().contents;
-        let mut client =
-            AuthenticationService::connect("localhost:7776", &enclave_info, &as_root_ca_cert)
-                .unwrap();
-        let token = client.user_login(ADMIN_ID, ADMIN_PASSWORD).unwrap();
-        client.set_credential(ADMIN_ID, &token);
-        let _ = client.user_register(USER_ID, USER_PASSWORD, "PlatformAdmin", "");
-        let token = client.user_login(USER_ID, USER_PASSWORD).unwrap();
-
-        let mut client =
-            FrontendService::connect("localhost:7777", &enclave_info, &as_root_ca_cert).unwrap();
-        client.set_credential(USER_ID, &token);
-        let request = RegisterFunctionRequest::default();
+        let mut client = get_frontend_client();
+        let request = RegisterFunctionRequestBuilder::new().build();
         let function_id = client
             .register_function_with_request(request)
             .unwrap()
             .function_id;
 
-        let request = GetFunctionRequest::new(function_id);
+        let request = GetFunctionRequest::new(function_id.try_into().unwrap());
         let response = client.get_function_with_request(request);
         assert!(response.is_ok());
 
@@ -720,7 +717,7 @@
             .outputs_ownership(hashmap!("output" =>  vec!["frontend_user", "mock_user"]));
         let response = client.create_task_with_request(request);
         assert!(response.is_ok());
-        let task_id = response.unwrap().task_id;
+        let task_id = response.unwrap().task_id.try_into().unwrap();
 
         let request = GetTaskRequest::new(task_id);
         let response = client.get_task_with_request(request);
@@ -729,20 +726,7 @@
 
     #[test]
     fn test_assign_data() {
-        let enclave_info = EnclaveInfo::from_file(ENCLAVE_INFO_PATH).unwrap();
-        let bytes = fs::read(AS_ROOT_CA_CERT_PATH).unwrap();
-        let as_root_ca_cert = pem::parse(bytes).unwrap().contents;
-        let mut client =
-            AuthenticationService::connect("localhost:7776", &enclave_info, &as_root_ca_cert)
-                .unwrap();
-        let token = client.user_login(ADMIN_ID, ADMIN_PASSWORD).unwrap();
-        client.set_credential(ADMIN_ID, &token);
-        let _ = client.user_register(USER_ID, USER_PASSWORD, "PlatformAdmin", "");
-        let token = client.user_login(USER_ID, USER_PASSWORD).unwrap();
-
-        let mut client =
-            FrontendService::connect("localhost:7777", &enclave_info, &as_root_ca_cert).unwrap();
-        client.set_credential(USER_ID, &token);
+        let mut client = get_frontend_client();
         let function_id = "function-00000000-0000-0000-0000-000000000002";
         let function_arguments = hashmap!("arg1" => "arg1_value");
         let outputs_ownership = hashmap!("output" => vec![USER_ID.to_string()]);
@@ -767,20 +751,7 @@
 
     #[test]
     fn test_assign_data_err() {
-        let enclave_info = EnclaveInfo::from_file(ENCLAVE_INFO_PATH).unwrap();
-        let bytes = fs::read(AS_ROOT_CA_CERT_PATH).unwrap();
-        let as_root_ca_cert = pem::parse(bytes).unwrap().contents;
-        let mut client =
-            AuthenticationService::connect("localhost:7776", &enclave_info, &as_root_ca_cert)
-                .unwrap();
-        let token = client.user_login(ADMIN_ID, ADMIN_PASSWORD).unwrap();
-        client.set_credential(ADMIN_ID, &token);
-        let _ = client.user_register(USER_ID, USER_PASSWORD, "PlatformAdmin", "");
-        let token = client.user_login(USER_ID, USER_PASSWORD).unwrap();
-
-        let mut client =
-            FrontendService::connect("localhost:7777", &enclave_info, &as_root_ca_cert).unwrap();
-        client.set_credential(USER_ID, &token);
+        let mut client = get_frontend_client();
         let function_id = "function-00000000-0000-0000-0000-000000000002";
         let function_arguments = hashmap!("arg1" => "arg1_value");
         let outputs_ownership = hashmap!("output" => vec!["incorrect_user".to_string()]);
@@ -806,20 +777,7 @@
 
     #[test]
     fn test_approve_task() {
-        let enclave_info = EnclaveInfo::from_file(ENCLAVE_INFO_PATH).unwrap();
-        let bytes = fs::read(AS_ROOT_CA_CERT_PATH).unwrap();
-        let as_root_ca_cert = pem::parse(bytes).unwrap().contents;
-        let mut client =
-            AuthenticationService::connect("localhost:7776", &enclave_info, &as_root_ca_cert)
-                .unwrap();
-        let token = client.user_login(ADMIN_ID, ADMIN_PASSWORD).unwrap();
-        client.set_credential(ADMIN_ID, &token);
-        let _ = client.user_register(USER_ID, USER_PASSWORD, "PlatformAdmin", "");
-        let token = client.user_login(USER_ID, USER_PASSWORD).unwrap();
-
-        let mut client =
-            FrontendService::connect("localhost:7777", &enclave_info, &as_root_ca_cert).unwrap();
-        client.set_credential(USER_ID, &token);
+        let mut client = get_frontend_client();
         let function_id = "function-00000000-0000-0000-0000-000000000002";
         let function_arguments = hashmap!("arg1" => "arg1_value");
         let outputs_ownership = hashmap!("output" => vec![USER_ID.to_string()]);
@@ -845,20 +803,7 @@
 
     #[test]
     fn test_cancel_task() {
-        let enclave_info = EnclaveInfo::from_file(ENCLAVE_INFO_PATH).unwrap();
-        let bytes = fs::read(AS_ROOT_CA_CERT_PATH).unwrap();
-        let as_root_ca_cert = pem::parse(bytes).unwrap().contents;
-        let mut client =
-            AuthenticationService::connect("localhost:7776", &enclave_info, &as_root_ca_cert)
-                .unwrap();
-        let token = client.user_login(ADMIN_ID, ADMIN_PASSWORD).unwrap();
-        client.set_credential(ADMIN_ID, &token);
-        let _ = client.user_register(USER_ID, USER_PASSWORD, "PlatformAdmin", "");
-        let token = client.user_login(USER_ID, USER_PASSWORD).unwrap();
-
-        let mut client =
-            FrontendService::connect("localhost:7777", &enclave_info, &as_root_ca_cert).unwrap();
-        client.set_credential(USER_ID, &token);
+        let mut client = get_frontend_client();
         let function_id = "function-00000000-0000-0000-0000-000000000002";
         let function_arguments = hashmap!("arg1" => "arg1_value");
         let outputs_ownership = hashmap!("output" => vec![USER_ID.to_string()]);
diff --git a/services/access_control/enclave/Cargo.toml b/services/access_control/enclave/Cargo.toml
index 6e61bc1..cf33cda 100644
--- a/services/access_control/enclave/Cargo.toml
+++ b/services/access_control/enclave/Cargo.toml
@@ -49,6 +49,7 @@
 serde      = { version = "1.0.92" }
 serde_json = { version = "1.0.39" }
 thiserror  = { version = "1.0.9" }
+tokio      = { version = "1.0", features = ["rt-multi-thread", "time", "macros"] }
 ring       = { version = "0.16.5" }
 rand       = { version = "0.8.5" }
 
diff --git a/services/access_control/enclave/src/error.rs b/services/access_control/enclave/src/error.rs
index 87fa7de..033005a 100644
--- a/services/access_control/enclave/src/error.rs
+++ b/services/access_control/enclave/src/error.rs
@@ -15,7 +15,6 @@
 // specific language governing permissions and limitations
 // under the License.
 
-use teaclave_types::TeaclaveServiceResponseError;
 use thiserror::Error;
 
 #[derive(Error, Debug)]
@@ -24,8 +23,8 @@
     AccessControlError,
 }
 
-impl From<TeaclavAccessControlError> for TeaclaveServiceResponseError {
+impl From<TeaclavAccessControlError> for teaclave_rpc::Status {
     fn from(error: TeaclavAccessControlError) -> Self {
-        TeaclaveServiceResponseError::RequestError(error.to_string())
+        teaclave_rpc::Status::permission_denied(error.to_string())
     }
 }
diff --git a/services/access_control/enclave/src/lib.rs b/services/access_control/enclave/src/lib.rs
index c6dbb7b..056e713 100644
--- a/services/access_control/enclave/src/lib.rs
+++ b/services/access_control/enclave/src/lib.rs
@@ -30,11 +30,8 @@
     ACCESS_CONTROL_INBOUND_SERVICES, AS_ROOT_CA_CERT, AUDITOR_PUBLIC_KEYS,
 };
 use teaclave_config::RuntimeConfig;
-use teaclave_proto::teaclave_access_control_service::{
-    TeaclaveAccessControlRequest, TeaclaveAccessControlResponse,
-};
-use teaclave_rpc::config::SgxTrustedTlsServerConfig;
-use teaclave_rpc::server::SgxTrustedTlsServer;
+use teaclave_proto::teaclave_access_control_service::TeaclaveAccessControlServer;
+use teaclave_rpc::{config::SgxTrustedTlsServerConfig, transport::Server};
 use teaclave_service_enclave_utils::ServiceEnclave;
 use teaclave_types::{EnclaveInfo, TeeServiceError, TeeServiceResult};
 
@@ -42,7 +39,10 @@
 mod error;
 mod service;
 
-fn start_service(config: &RuntimeConfig) -> Result<()> {
+// Sets the number of worker threads the Runtime will use.
+const N_WORKERS: usize = 8;
+
+async fn start_service(config: &RuntimeConfig) -> Result<()> {
     let listen_address = config.internal_endpoints.access_control.listen_address;
     let attestation_config = AttestationConfig::from_teaclave_config(config)?;
     let attested_tls_config = RemoteAttestation::new(attestation_config)
@@ -61,34 +61,40 @@
             None => Err(anyhow!("cannot get enclave attribute of {}", service)),
         })
         .collect::<Result<_>>()?;
+
     let server_config = SgxTrustedTlsServerConfig::from_attested_tls_config(attested_tls_config)?
         .attestation_report_verifier(
-        accepted_enclave_attrs,
-        AS_ROOT_CA_CERT,
-        verifier::universal_quote_verifier,
-    )?;
-
+            accepted_enclave_attrs,
+            AS_ROOT_CA_CERT,
+            verifier::universal_quote_verifier,
+        )?
+        .into();
     acs::init_acs()?;
-    let mut server = SgxTrustedTlsServer::<
-        TeaclaveAccessControlResponse,
-        TeaclaveAccessControlRequest,
-    >::new(listen_address, server_config);
+
     let service = service::TeaclaveAccessControlService::new();
-    match server.start(service) {
-        Ok(_) => (),
-        Err(e) => {
-            error!("Service exit, error: {}.", e);
-        }
-    }
+
+    Server::builder()
+        .tls_config(server_config)
+        .map_err(|_| anyhow::anyhow!("TeaclaveFrontendServer tls config error"))?
+        .add_service(TeaclaveAccessControlServer::new(service))
+        .serve(listen_address)
+        .await?;
     Ok(())
 }
 
 #[handle_ecall]
 fn handle_start_service(input: &StartServiceInput) -> TeeServiceResult<StartServiceOutput> {
-    match start_service(&input.config) {
+    let result = tokio::runtime::Builder::new_multi_thread()
+        .worker_threads(N_WORKERS)
+        .enable_all()
+        .build()
+        .map_err(|_| TeeServiceError::SgxError)?
+        .block_on(start_service(&input.config));
+
+    match result {
         Ok(_) => Ok(StartServiceOutput),
         Err(e) => {
-            log::error!("Failed to start the service: {}", e);
+            error!("Failed to run service: {}", e);
             Err(TeeServiceError::ServiceError)
         }
     }
@@ -122,7 +128,7 @@
         if crate::acs::init_acs().is_err() {
             return false;
         }
-        run_tests!(
+        run_async_tests!(
             service::tests::user_access_data,
             service::tests::user_access_function,
             service::tests::user_access_task,
diff --git a/services/access_control/enclave/src/service.rs b/services/access_control/enclave/src/service.rs
index 4c67512..b733ddd 100644
--- a/services/access_control/enclave/src/service.rs
+++ b/services/access_control/enclave/src/service.rs
@@ -22,11 +22,10 @@
     AuthorizeFunctionResponse, AuthorizeStagedTaskRequest, AuthorizeStagedTaskResponse,
     AuthorizeTaskRequest, AuthorizeTaskResponse, TeaclaveAccessControl,
 };
-use teaclave_rpc::Request;
-use teaclave_service_enclave_utils::{bail, teaclave_service};
+use teaclave_rpc::{Request, Response};
+use teaclave_service_enclave_utils::bail;
 use teaclave_types::TeaclaveServiceResponseResult;
 
-#[teaclave_service(teaclave_access_control_service, TeaclaveAccessControl)]
 #[derive(Clone)]
 pub(crate) struct TeaclaveAccessControlService {
     access_control_module: AccessControlModule,
@@ -40,60 +39,61 @@
     }
 }
 
+#[teaclave_rpc::async_trait]
 impl TeaclaveAccessControl for TeaclaveAccessControlService {
-    fn authorize_data(
+    async fn authorize_data(
         &self,
         request: Request<AuthorizeDataRequest>,
     ) -> TeaclaveServiceResponseResult<AuthorizeDataResponse> {
-        let request = request.message;
+        let request = request.into_inner();
         let request =
             EnforceRequest::UserAccessData(request.subject_user_id, request.object_data_id);
         match self.access_control_module.enforce_request(request) {
             Ok(accept) => {
                 let response = AuthorizeDataResponse::new(accept);
-                Ok(response)
+                Ok(Response::new(response))
             }
             Err(_) => Err(TeaclavAccessControlError::AccessControlError.into()),
         }
     }
 
-    fn authorize_function(
+    async fn authorize_function(
         &self,
         request: Request<AuthorizeFunctionRequest>,
     ) -> TeaclaveServiceResponseResult<AuthorizeFunctionResponse> {
-        let request = request.message;
+        let request = request.into_inner();
         let request =
             EnforceRequest::UserAccessFunction(request.subject_user_id, request.object_function_id);
         match self.access_control_module.enforce_request(request) {
             Ok(accept) => {
                 let response = AuthorizeFunctionResponse::new(accept);
-                Ok(response)
+                Ok(Response::new(response))
             }
             Err(_) => Err(TeaclavAccessControlError::AccessControlError.into()),
         }
     }
 
-    fn authorize_task(
+    async fn authorize_task(
         &self,
         request: Request<AuthorizeTaskRequest>,
     ) -> TeaclaveServiceResponseResult<AuthorizeTaskResponse> {
-        let request = request.message;
+        let request = request.into_inner();
         let request =
             EnforceRequest::UserAccessTask(request.subject_user_id, request.object_task_id);
         match self.access_control_module.enforce_request(request) {
             Ok(accept) => {
                 let response = AuthorizeTaskResponse::new(accept);
-                Ok(response)
+                Ok(Response::new(response))
             }
             Err(_) => Err(TeaclavAccessControlError::AccessControlError.into()),
         }
     }
 
-    fn authorize_staged_task(
+    async fn authorize_staged_task(
         &self,
         request: Request<AuthorizeStagedTaskRequest>,
     ) -> TeaclaveServiceResponseResult<AuthorizeStagedTaskResponse> {
-        let request = request.message;
+        let request = request.into_inner();
         let enforce_access_function_request = EnforceRequest::TaskAccessFunction(
             request.subject_task_id.clone(),
             request.object_function_id,
@@ -104,7 +104,7 @@
         {
             Ok(accept) => {
                 if !accept {
-                    return Ok(AuthorizeStagedTaskResponse::new(false));
+                    return Ok(Response::new(AuthorizeStagedTaskResponse::new(false)));
                 }
             }
             Err(_) => bail!(TeaclavAccessControlError::AccessControlError),
@@ -120,7 +120,7 @@
             {
                 Ok(accept) => {
                     if !accept {
-                        return Ok(AuthorizeStagedTaskResponse::new(false));
+                        return Ok(Response::new(AuthorizeStagedTaskResponse::new(false)));
                     }
                 }
                 Err(_) => bail!(TeaclavAccessControlError::AccessControlError),
@@ -137,13 +137,13 @@
             {
                 Ok(accept) => {
                     if !accept {
-                        return Ok(AuthorizeStagedTaskResponse::new(false));
+                        return Ok(Response::new(AuthorizeStagedTaskResponse::new(false)));
                     }
                 }
                 Err(_) => bail!(TeaclavAccessControlError::AccessControlError),
             }
         }
-        Ok(AuthorizeStagedTaskResponse { accept: true })
+        Ok(Response::new(AuthorizeStagedTaskResponse { accept: true }))
     }
 }
 
@@ -152,102 +152,101 @@
     use super::*;
     use teaclave_rpc::IntoRequest;
 
-    pub fn user_access_data() {
+    pub async fn user_access_data() {
         let service = TeaclaveAccessControlService::new();
         let request = AuthorizeDataRequest::new("mock_user_a", "mock_data").into_request();
-        let response = service.authorize_data(request);
+        let response = service.authorize_data(request).await;
         assert!(response.is_ok());
-        assert!(response.unwrap().accept);
+        assert!(response.unwrap().into_inner().accept);
 
         let request = AuthorizeDataRequest::new("mock_user_b", "mock_data").into_request();
-        let response = service.authorize_data(request);
+        let response = service.authorize_data(request).await;
         assert!(response.is_ok());
-        assert!(response.unwrap().accept);
+        assert!(response.unwrap().into_inner().accept);
 
         let request = AuthorizeDataRequest::new("mock_user_c", "mock_data").into_request();
-        let response = service.authorize_data(request);
+        let response = service.authorize_data(request).await;
         assert!(response.is_ok());
-        assert!(response.unwrap().accept);
+        assert!(response.unwrap().into_inner().accept);
 
         let request = AuthorizeDataRequest::new("mock_user_d", "mock_data").into_request();
-        let response = service.authorize_data(request);
+        let response = service.authorize_data(request).await;
         assert!(response.is_ok());
-        assert!(!response.unwrap().accept);
+        assert!(!response.unwrap().into_inner().accept);
 
         let request = AuthorizeDataRequest::new("mock_user_a", "mock_data_b").into_request();
-        let response = service.authorize_data(request);
+        let response = service.authorize_data(request).await;
         assert!(response.is_ok());
-        assert!(!response.unwrap().accept);
+        assert!(!response.unwrap().into_inner().accept);
     }
 
-    pub fn user_access_function() {
+    pub async fn user_access_function() {
         let service = TeaclaveAccessControlService::new();
         let request =
             AuthorizeFunctionRequest::new("mock_public_function_owner", "mock_public_function")
                 .into_request();
-        let response = service.authorize_function(request);
+        let response = service.authorize_function(request).await;
         assert!(response.is_ok());
-        assert!(response.unwrap().accept);
-
+        assert!(response.unwrap().into_inner().accept);
         let request =
             AuthorizeFunctionRequest::new("mock_private_function_owner", "mock_private_function")
                 .into_request();
-        let response = service.authorize_function(request);
+        let response = service.authorize_function(request).await;
         assert!(response.is_ok());
-        assert!(response.unwrap().accept);
+        assert!(response.unwrap().into_inner().accept);
 
         let request =
             AuthorizeFunctionRequest::new("mock_private_function_owner", "mock_public_function")
                 .into_request();
-        let response = service.authorize_function(request);
+        let response = service.authorize_function(request).await;
         assert!(response.is_ok());
-        assert!(response.unwrap().accept);
+        assert!(response.unwrap().into_inner().accept);
 
         let request =
             AuthorizeFunctionRequest::new("mock_public_function_owner", "mock_private_function")
                 .into_request();
-        let response = service.authorize_function(request);
+        let response = service.authorize_function(request).await;
         assert!(response.is_ok());
-        assert!(!response.unwrap().accept);
+        assert!(!response.unwrap().into_inner().accept);
     }
 
-    pub fn user_access_task() {
+    pub async fn user_access_task() {
         let service = TeaclaveAccessControlService::new();
         let request = AuthorizeTaskRequest::new("mock_participant_a", "mock_task").into_request();
-        let response = service.authorize_task(request);
+        let response = service.authorize_task(request).await;
         assert!(response.is_ok());
-        assert!(response.unwrap().accept);
+        assert!(response.unwrap().into_inner().accept);
 
         let request = AuthorizeTaskRequest::new("mock_participant_b", "mock_task").into_request();
-        let response = service.authorize_task(request);
+        let response = service.authorize_task(request).await;
         assert!(response.is_ok());
-        assert!(response.unwrap().accept);
+        assert!(response.unwrap().into_inner().accept);
 
         let request = AuthorizeTaskRequest::new("mock_participant_c", "mock_task").into_request();
-        let response = service.authorize_task(request);
+        let response = service.authorize_task(request).await;
         assert!(response.is_ok());
-        assert!(!response.unwrap().accept);
+        assert!(!response.unwrap().into_inner().accept);
     }
 
-    pub fn task_access_function() {
+    pub async fn task_access_function() {
         let service = TeaclaveAccessControlService::new();
         let mut request = get_correct_authorized_stage_task_req();
         request.object_function_id = "mock_staged_allowed_private_function".to_string();
-        let response = service.authorize_staged_task(request.into_request());
+        let response = service.authorize_staged_task(request.into_request()).await;
         assert!(response.is_ok());
-        assert!(response.unwrap().accept);
+        assert!(response.unwrap().into_inner().accept);
 
         let mut request = get_correct_authorized_stage_task_req();
         request.object_function_id = "mock_staged_public_function".to_string();
-        let response = service.authorize_staged_task(request.into_request());
+        let response = service.authorize_staged_task(request.into_request()).await;
         assert!(response.is_ok());
-        assert!(response.unwrap().accept);
+        assert!(response.unwrap().into_inner().accept);
 
         let mut request = get_correct_authorized_stage_task_req();
         request.object_function_id = "mock_staged_disallowed_private_function".to_string();
-        let response = service.authorize_staged_task(request.into_request());
+        let response = service.authorize_staged_task(request.into_request()).await;
         assert!(response.is_ok());
-        assert!(!response.unwrap().accept);
+        assert!(!response.unwrap().into_inner().accept);
     }
 
     fn get_correct_authorized_stage_task_req() -> AuthorizeStagedTaskRequest {
@@ -266,43 +265,42 @@
             ],
         }
     }
-    pub fn task_access_data() {
+
+    pub async fn task_access_data() {
         let service = TeaclaveAccessControlService::new();
         let request = get_correct_authorized_stage_task_req().into_request();
-        let response = service.authorize_staged_task(request);
+        let response = service.authorize_staged_task(request).await;
         assert!(response.is_ok());
-        assert!(response.unwrap().accept);
-
+        assert!(response.unwrap().into_inner().accept);
         let mut request = get_correct_authorized_stage_task_req();
         request
             .object_input_data_id_list
             .push("mock_staged_disallowed_data1".to_string());
-        let response = service.authorize_staged_task(request.into_request());
+        let response = service.authorize_staged_task(request.into_request()).await;
         assert!(response.is_ok());
-        assert!(!response.unwrap().accept);
-
+        assert!(!response.unwrap().into_inner().accept);
         let mut request = get_correct_authorized_stage_task_req();
         request
             .object_input_data_id_list
             .push("mock_staged_disallowed_data2".to_string());
-        let response = service.authorize_staged_task(request.into_request());
+        let response = service.authorize_staged_task(request.into_request()).await;
         assert!(response.is_ok());
-        assert!(!response.unwrap().accept);
+        assert!(!response.unwrap().into_inner().accept);
 
         let mut request = get_correct_authorized_stage_task_req();
         request
             .object_output_data_id_list
             .push("mock_staged_disallowed_data1".to_string());
-        let response = service.authorize_staged_task(request.into_request());
+        let response = service.authorize_staged_task(request.into_request()).await;
         assert!(response.is_ok());
-        assert!(!response.unwrap().accept);
+        assert!(!response.unwrap().into_inner().accept);
 
         let mut request = get_correct_authorized_stage_task_req();
         request
             .object_output_data_id_list
             .push("mock_staged_disallowed_data2".to_string());
-        let response = service.authorize_staged_task(request.into_request());
+        let response = service.authorize_staged_task(request.into_request()).await;
         assert!(response.is_ok());
-        assert!(!response.unwrap().accept);
+        assert!(!response.unwrap().into_inner().accept);
     }
 }
diff --git a/services/authentication/enclave/Cargo.toml b/services/authentication/enclave/Cargo.toml
index 13387d5..9362af6 100644
--- a/services/authentication/enclave/Cargo.toml
+++ b/services/authentication/enclave/Cargo.toml
@@ -48,8 +48,8 @@
 log       = { version = "0.4.17", features = ["release_max_level_info"] }
 serde     = { version = "1.0.92" }
 serde_json = { version = "1.0.39" }
-
 thiserror = { version = "1.0.9" }
+tokio     = { version = "1.0", features = ["rt-multi-thread", "time", "macros"] }
 ring      = { version = "0.16.5" }
 rand      = { version = "0.8.5" }
 jsonwebtoken = { version = "7.2.0" }
diff --git a/services/authentication/enclave/src/api_service.rs b/services/authentication/enclave/src/api_service.rs
index 38d605b..7fccd04 100644
--- a/services/authentication/enclave/src/api_service.rs
+++ b/services/authentication/enclave/src/api_service.rs
@@ -20,29 +20,24 @@
 use crate::user_db::DbClient;
 use crate::user_info::UserInfo;
 
+use std::sync::{Arc, Mutex};
 use std::time::{Duration, SystemTime, UNIX_EPOCH};
 #[allow(unused_imports)]
 use std::untrusted::time::SystemTimeEx;
 use teaclave_proto::teaclave_authentication_service::*;
-use teaclave_rpc::Request;
-use teaclave_service_enclave_utils::{bail, ensure, teaclave_service};
+use teaclave_rpc::{Request, Response};
+use teaclave_service_enclave_utils::{bail, ensure};
 use teaclave_types::{TeaclaveServiceResponseResult, UserRole};
-
-#[teaclave_service(
-    teaclave_authentication_service,
-    TeaclaveAuthenticationApi,
-    TeaclaveAuthenticationError
-)]
 #[derive(Clone)]
 pub(crate) struct TeaclaveAuthenticationApiService {
-    db_client: DbClient,
+    db_client: Arc<Mutex<DbClient>>,
     jwt_secret: Vec<u8>,
 }
 
 impl TeaclaveAuthenticationApiService {
     pub(crate) fn new(db_client: DbClient, jwt_secret: Vec<u8>) -> Self {
         Self {
-            db_client,
+            db_client: Arc::new(Mutex::new(db_client)),
             jwt_secret,
         }
     }
@@ -52,7 +47,7 @@
         id: &str,
         token: &str,
     ) -> Result<UserRole, AuthenticationError> {
-        let user: UserInfo = match self.db_client.get_user(id) {
+        let user: UserInfo = match self.db_client.lock().unwrap().get_user(id) {
             Ok(value) => value,
             Err(_) => bail!(AuthenticationError::InvalidUserId),
         };
@@ -66,32 +61,42 @@
             Err(_) => bail!(AuthenticationError::IncorrectToken),
         }
     }
-}
 
-impl TeaclaveAuthenticationApi for TeaclaveAuthenticationApiService {
-    fn user_register(
+    fn validate_credential_in_request<T>(
         &self,
-        request: Request<UserRegisterRequest>,
-    ) -> TeaclaveServiceResponseResult<UserRegisterResponse> {
+        request: &Request<T>,
+    ) -> Result<UserRole, AuthenticationServiceError> {
         let id: String = request
-            .metadata
+            .metadata()
             .get("id")
+            .and_then(|x| x.to_str().ok())
             .ok_or(AuthenticationServiceError::MissingUserId)?
             .into();
         let token: String = request
-            .metadata
+            .metadata()
             .get("token")
+            .and_then(|x| x.to_str().ok())
             .ok_or(AuthenticationServiceError::MissingToken)?
             .into();
-
         let requester_role = self.validate_user_credential(&id, &token)?;
+        Ok(requester_role)
+    }
+}
 
-        let request = request.message;
+#[teaclave_rpc::async_trait]
+impl TeaclaveAuthenticationApi for TeaclaveAuthenticationApiService {
+    async fn user_register(
+        &self,
+        request: Request<UserRegisterRequest>,
+    ) -> TeaclaveServiceResponseResult<UserRegisterResponse> {
+        let requester_role = self.validate_credential_in_request(&request)?;
+
+        let request = request.get_ref();
         ensure!(
             !request.id.is_empty(),
             AuthenticationServiceError::InvalidUserId
         );
-        if self.db_client.get_user(&request.id).is_ok() {
+        if self.db_client.lock().unwrap().get_user(&request.id).is_ok() {
             bail!(AuthenticationServiceError::UserIdExist);
         }
         let role = UserRole::new(&request.role, &request.attribute);
@@ -101,39 +106,35 @@
         );
 
         ensure!(
-            authorize_user_register(&requester_role, &request),
+            authorize_user_register(&requester_role, request),
             AuthenticationServiceError::PermissionDenied
         );
 
         let new_user = UserInfo::new(&request.id, &request.password, role);
-        match self.db_client.create_user(&new_user) {
-            Ok(_) => Ok(UserRegisterResponse {}),
+        match self.db_client.lock().unwrap().create_user(&new_user) {
+            Ok(_) => Ok(Response::new(UserRegisterResponse {})),
             Err(e) => bail!(AuthenticationServiceError::Service(e.into())),
         }
     }
 
-    fn user_update(
+    async fn user_update(
         &self,
         request: Request<UserUpdateRequest>,
     ) -> TeaclaveServiceResponseResult<UserUpdateResponse> {
-        let id: String = request
-            .metadata
-            .get("id")
-            .ok_or(AuthenticationServiceError::MissingUserId)?
-            .into();
-        let token: String = request
-            .metadata
-            .get("token")
-            .ok_or(AuthenticationServiceError::MissingToken)?
-            .into();
-        let requester_role = self.validate_user_credential(&id, &token)?;
+        let requester_role = self.validate_credential_in_request(&request)?;
 
-        let request = request.message;
+        let request = request.get_ref();
         ensure!(
             !request.id.is_empty(),
             AuthenticationServiceError::InvalidUserId
         );
-        if self.db_client.get_user(&request.id).is_err() {
+        if self
+            .db_client
+            .lock()
+            .unwrap()
+            .get_user(&request.id)
+            .is_err()
+        {
             bail!(AuthenticationServiceError::InvalidUserId);
         }
         let role = UserRole::new(&request.role, &request.attribute);
@@ -143,22 +144,22 @@
         );
 
         ensure!(
-            authorize_user_update(&requester_role, &request),
+            authorize_user_update(&requester_role, request),
             AuthenticationServiceError::PermissionDenied
         );
 
         let updated_user = UserInfo::new(&request.id, &request.password, role);
-        match self.db_client.update_user(&updated_user) {
-            Ok(_) => Ok(UserUpdateResponse {}),
+        match self.db_client.lock().unwrap().update_user(&updated_user) {
+            Ok(_) => Ok(Response::new(UserUpdateResponse {})),
             Err(e) => bail!(AuthenticationServiceError::Service(e.into())),
         }
     }
 
-    fn user_login(
+    async fn user_login(
         &self,
         request: Request<UserLoginRequest>,
     ) -> TeaclaveServiceResponseResult<UserLoginResponse> {
-        let request = request.message;
+        let request = request.get_ref();
         ensure!(!request.id.is_empty(), AuthenticationError::InvalidUserId);
         ensure!(
             !request.password.is_empty(),
@@ -166,6 +167,8 @@
         );
         let user = self
             .db_client
+            .lock()
+            .unwrap()
             .get_user(&request.id)
             .map_err(|_| AuthenticationError::UserIdNotFound)?;
         if !user.verify_password(&request.password) {
@@ -176,64 +179,52 @@
                 .map_err(|e| AuthenticationServiceError::Service(e.into()))?;
             let exp = (now + Duration::from_secs(24 * 60 * 60)).as_secs();
             match user.get_token(exp, &self.jwt_secret) {
-                Ok(token) => Ok(UserLoginResponse { token }),
+                Ok(token) => Ok(Response::new(UserLoginResponse { token })),
                 Err(e) => bail!(AuthenticationServiceError::Service(e)),
             }
         }
     }
 
-    fn user_change_password(
+    async fn user_change_password(
         &self,
         request: Request<UserChangePasswordRequest>,
     ) -> TeaclaveServiceResponseResult<UserChangePasswordResponse> {
-        let id: String = request
-            .metadata
-            .get("id")
-            .ok_or(AuthenticationServiceError::MissingUserId)?
-            .into();
-        let token: String = request
-            .metadata
-            .get("token")
-            .ok_or(AuthenticationServiceError::MissingToken)?
-            .into();
-        let requester_role = self.validate_user_credential(&id, &token)?;
+        let requester_role = self.validate_credential_in_request(&request)?;
 
-        let request = request.message;
+        let id: String = request
+            .metadata()
+            .get("id")
+            .and_then(|x| x.to_str().ok())
+            .unwrap()
+            .into();
+        let request = request.get_ref();
         ensure!(
             !request.password.is_empty(),
             AuthenticationError::InvalidPassword
         );
         let updated_user = UserInfo::new(&id, &request.password, requester_role);
 
-        match self.db_client.update_user(&updated_user) {
-            Ok(_) => Ok(UserChangePasswordResponse {}),
+        match self.db_client.lock().unwrap().update_user(&updated_user) {
+            Ok(_) => Ok(Response::new(UserChangePasswordResponse {})),
             Err(e) => bail!(AuthenticationServiceError::Service(e.into())),
         }
     }
 
-    fn reset_user_password(
+    async fn reset_user_password(
         &self,
         request: Request<ResetUserPasswordRequest>,
     ) -> TeaclaveServiceResponseResult<ResetUserPasswordResponse> {
-        let id: String = request
-            .metadata
-            .get("id")
-            .ok_or(AuthenticationServiceError::MissingUserId)?
-            .into();
-        let token: String = request
-            .metadata
-            .get("token")
-            .ok_or(AuthenticationServiceError::MissingToken)?
-            .into();
-        let requester_role = self.validate_user_credential(&id, &token)?;
+        let requester_role = self.validate_credential_in_request(&request)?;
 
-        let request = request.message;
+        let request = request.get_ref();
         ensure!(
             !request.id.is_empty(),
             AuthenticationServiceError::InvalidUserId
         );
         let user = self
             .db_client
+            .lock()
+            .unwrap()
             .get_user(&request.id)
             .map_err(|_| AuthenticationServiceError::PermissionDenied)?;
 
@@ -247,37 +238,29 @@
             .to_simple()
             .encode_lower(&mut encode_buffer);
         let updated_user = UserInfo::new(&request.id, new_password, user.role);
-        match self.db_client.update_user(&updated_user) {
-            Ok(_) => Ok(ResetUserPasswordResponse {
+        match self.db_client.lock().unwrap().update_user(&updated_user) {
+            Ok(_) => Ok(Response::new(ResetUserPasswordResponse {
                 password: new_password.to_string(),
-            }),
+            })),
             Err(e) => bail!(AuthenticationServiceError::Service(e.into())),
         }
     }
 
-    fn delete_user(
+    async fn delete_user(
         &self,
         request: Request<DeleteUserRequest>,
     ) -> TeaclaveServiceResponseResult<DeleteUserResponse> {
-        let id: String = request
-            .metadata
-            .get("id")
-            .ok_or(AuthenticationServiceError::MissingUserId)?
-            .into();
-        let token: String = request
-            .metadata
-            .get("token")
-            .ok_or(AuthenticationServiceError::MissingToken)?
-            .into();
-        let requester_role = self.validate_user_credential(&id, &token)?;
+        let requester_role = self.validate_credential_in_request(&request)?;
 
-        let request = request.message;
+        let request = request.get_ref();
         ensure!(
             !request.id.is_empty(),
             AuthenticationServiceError::InvalidUserId
         );
         let user = self
             .db_client
+            .lock()
+            .unwrap()
             .get_user(&request.id)
             .map_err(|_| AuthenticationServiceError::PermissionDenied)?;
 
@@ -285,46 +268,40 @@
             authorize_delete_user(&requester_role, &user),
             AuthenticationServiceError::PermissionDenied
         );
-        match self.db_client.delete_user(&request.id) {
-            Ok(_) => Ok(DeleteUserResponse {}),
+        match self.db_client.lock().unwrap().delete_user(&request.id) {
+            Ok(_) => Ok(Response::new(DeleteUserResponse {})),
             Err(e) => bail!(AuthenticationServiceError::Service(e.into())),
         }
     }
 
-    fn list_users(
+    async fn list_users(
         &self,
         request: Request<ListUsersRequest>,
     ) -> TeaclaveServiceResponseResult<ListUsersResponse> {
-        let id: String = request
-            .metadata
-            .get("id")
-            .ok_or(AuthenticationServiceError::MissingUserId)?
-            .into();
-        let token: String = request
-            .metadata
-            .get("token")
-            .ok_or(AuthenticationServiceError::MissingToken)?
-            .into();
-        let requester_role = self.validate_user_credential(&id, &token)?;
+        let requester_role = self.validate_credential_in_request(&request)?;
 
-        let request = request.message;
+        let request = request.get_ref();
         ensure!(
             !request.id.is_empty(),
             AuthenticationServiceError::InvalidUserId
         );
 
         ensure!(
-            authorize_list_users(&requester_role, &request),
+            authorize_list_users(&requester_role, request),
             AuthenticationServiceError::PermissionDenied
         );
 
         let users = match requester_role {
-            UserRole::PlatformAdmin => self.db_client.list_users(),
-            _ => self.db_client.list_users_by_attribute(&request.id),
+            UserRole::PlatformAdmin => self.db_client.lock().unwrap().list_users(),
+            _ => self
+                .db_client
+                .lock()
+                .unwrap()
+                .list_users_by_attribute(&request.id),
         };
 
         match users {
-            Ok(ids) => Ok(ListUsersResponse { ids }),
+            Ok(ids) => Ok(Response::new(ListUsersResponse { ids })),
             Err(e) => bail!(AuthenticationServiceError::Service(e.into())),
         }
     }
@@ -393,9 +370,8 @@
     use crate::user_db::*;
     use crate::user_info::*;
     use rand::RngCore;
-    use std::collections::HashMap;
     use std::vec;
-    use teaclave_rpc::IntoRequest;
+    use teaclave_rpc::{IntoRequest, MetadataMap};
 
     fn get_mock_service() -> TeaclaveAuthenticationApiService {
         let database = Database::open("").unwrap();
@@ -406,94 +382,104 @@
         crate::create_platform_admin_user(client, "admin", "teaclave").unwrap();
 
         TeaclaveAuthenticationApiService {
-            db_client: database.get_client(),
+            db_client: Arc::new(Mutex::new(database.get_client())),
             jwt_secret,
         }
     }
 
-    pub fn test_user_register() {
+    pub async fn test_user_register() {
         let service = get_mock_service();
         let request = UserLoginRequest::new("admin", "teaclave").into_request();
-        let response = service.user_login(request).unwrap();
+        let response = service.user_login(request).await.unwrap().into_inner();
 
-        let mut metadata = HashMap::new();
-        metadata.insert("id".to_owned(), "admin".to_owned());
-        metadata.insert("token".to_owned(), response.token);
+        let mut metadata = MetadataMap::new();
+        metadata.insert("id", "admin".parse().unwrap());
+        metadata.insert("token", response.token.parse().unwrap());
         let mut request =
             UserRegisterRequest::new("test_register_id", "test_password", "PlatformAdmin", "")
                 .into_request();
-        request.metadata = metadata;
-        assert!(service.user_register(request).is_ok());
+        let meta = request.metadata_mut();
+        *meta = metadata;
+        assert!(service.user_register(request).await.is_ok());
     }
 
-    pub fn test_user_update() {
+    pub async fn test_user_update() {
         let service = get_mock_service();
         let request = UserLoginRequest::new("admin", "teaclave").into_request();
-        let response = service.user_login(request).unwrap();
+        let response = service.user_login(request).await.unwrap().into_inner();
 
-        let mut metadata = HashMap::new();
-        metadata.insert("id".to_owned(), "admin".to_owned());
-        metadata.insert("token".to_owned(), response.token);
+        let mut metadata = MetadataMap::new();
+        metadata.insert("id", "admin".parse().unwrap());
+        metadata.insert("token", response.token.parse().unwrap());
         let mut request =
             UserRegisterRequest::new("test_update_id", "test_password", "PlatformAdmin", "")
                 .into_request();
-        request.metadata = metadata.clone();
-        assert!(service.user_register(request).is_ok());
+        let meta = request.metadata_mut();
+        *meta = metadata.clone();
+        assert!(service.user_register(request).await.is_ok());
 
         let mut request =
             UserUpdateRequest::new("test_update_id", "updated_password", "PlatformAdmin", "")
                 .into_request();
-        request.metadata = metadata.clone();
-        service.user_update(request).unwrap();
+        let meta = request.metadata_mut();
+        *meta = metadata.clone();
+        service.user_update(request).await.unwrap();
 
         let mut request =
             UserUpdateRequest::new("test_nonexist_id", "updated_password", "PlatformAdmin", "")
                 .into_request();
-        request.metadata = metadata;
-        assert!(service.user_update(request).is_err());
+        let meta = request.metadata_mut();
+        *meta = metadata;
+        assert!(service.user_update(request).await.is_err());
 
         let request = UserLoginRequest::new("test_update_id", "updated_password").into_request();
-        let response = service.user_login(request);
+        let response = service.user_login(request).await;
         assert!(response.is_ok());
     }
 
-    pub fn test_user_login() {
+    pub async fn test_user_login() {
         let service = get_mock_service();
 
         let request = UserLoginRequest::new("admin", "teaclave").into_request();
-        let response = service.user_login(request).unwrap();
+        let response = service.user_login(request).await.unwrap().into_inner();
 
-        let mut metadata = HashMap::new();
-        metadata.insert("id".to_owned(), "admin".to_owned());
-        metadata.insert("token".to_owned(), response.token);
+        let mut metadata = MetadataMap::new();
+        metadata.insert("id", "admin".parse().unwrap());
+        metadata.insert("token", response.token.parse().unwrap());
 
         let mut request =
             UserRegisterRequest::new("test_login_id", "test_password", "FunctionOwner", "")
                 .into_request();
-        request.metadata = metadata;
-        assert!(service.user_register(request).is_ok());
+        let meta = request.metadata_mut();
+        *meta = metadata;
+        assert!(service.user_register(request).await.is_ok());
 
         let request = UserLoginRequest::new("test_login_id", "test_password").into_request();
-        let response = service.user_login(request);
+        let response = service.user_login(request).await;
         assert!(response.is_ok());
 
-        let token = response.unwrap().token;
-        let user = service.db_client.get_user("test_login_id").unwrap();
+        let token = response.unwrap().into_inner().token;
+        let user = service
+            .db_client
+            .lock()
+            .unwrap()
+            .get_user("test_login_id")
+            .unwrap();
         assert!(user.validate_token(&service.jwt_secret, &token).is_ok());
 
         debug!("saved user_info: {:?}", user);
         let request = UserLoginRequest::new("test_login_id", "test_password1").into_request();
-        assert!(service.user_login(request).is_err());
+        assert!(service.user_login(request).await.is_err());
     }
 
-    pub fn test_user_change_password() {
+    pub async fn test_user_change_password() {
         let service = get_mock_service();
         let request = UserLoginRequest::new("admin", "teaclave").into_request();
-        let response = service.user_login(request).unwrap();
+        let response = service.user_login(request).await.unwrap().into_inner();
 
-        let mut metadata = HashMap::new();
-        metadata.insert("id".to_owned(), "admin".to_owned());
-        metadata.insert("token".to_owned(), response.token);
+        let mut metadata = MetadataMap::new();
+        metadata.insert("id", "admin".parse().unwrap());
+        metadata.insert("token", response.token.parse().unwrap());
         let mut request = UserRegisterRequest::new(
             "test_user_change_password_id",
             "test_password",
@@ -501,38 +487,39 @@
             "",
         )
         .into_request();
-        request.metadata = metadata;
-        assert!(service.user_register(request).is_ok());
+        *request.metadata_mut() = metadata;
+        assert!(service.user_register(request).await.is_ok());
 
         let request =
             UserLoginRequest::new("test_user_change_password_id", "test_password").into_request();
-        let response = service.user_login(request).unwrap();
-        let mut metadata = HashMap::new();
-        metadata.insert("id".to_owned(), "test_user_change_password_id".to_owned());
-        metadata.insert("token".to_owned(), response.token);
+        let response = service.user_login(request).await.unwrap().into_inner();
+        let mut metadata = MetadataMap::new();
+        metadata.insert("id", "test_user_change_password_id".parse().unwrap());
+        metadata.insert("token", response.token.parse().unwrap());
 
         let mut request = UserChangePasswordRequest::new("updated_password").into_request();
-        request.metadata = metadata.clone();
-        service.user_change_password(request).unwrap();
+        *request.metadata_mut() = metadata.clone();
+        service.user_change_password(request).await.unwrap();
 
         let mut request = UserChangePasswordRequest::new("").into_request();
-        request.metadata = metadata;
-        assert!(service.user_change_password(request).is_err());
+        *request.metadata_mut() = metadata;
+
+        assert!(service.user_change_password(request).await.is_err());
 
         let request = UserLoginRequest::new("test_user_change_password_id", "updated_password")
             .into_request();
-        let response = service.user_login(request);
+        let response = service.user_login(request).await;
         assert!(response.is_ok());
     }
 
-    pub fn test_reset_user_password() {
+    pub async fn test_reset_user_password() {
         let service = get_mock_service();
         let request = UserLoginRequest::new("admin", "teaclave").into_request();
-        let response = service.user_login(request).unwrap();
+        let response = service.user_login(request).await.unwrap().into_inner();
 
-        let mut metadata = HashMap::new();
-        metadata.insert("id".to_owned(), "admin".to_owned());
-        metadata.insert("token".to_owned(), response.token);
+        let mut metadata = MetadataMap::new();
+        metadata.insert("id", "admin".parse().unwrap());
+        metadata.insert("token", response.token.parse().unwrap());
         let mut request = UserRegisterRequest::new(
             "test_reset_user_password_id",
             "test_password",
@@ -540,57 +527,64 @@
             "",
         )
         .into_request();
-        request.metadata = metadata.clone();
-        assert!(service.user_register(request).is_ok());
+        *request.metadata_mut() = metadata.clone();
+        assert!(service.user_register(request).await.is_ok());
 
         let mut request =
             ResetUserPasswordRequest::new("test_reset_user_password_id").into_request();
-        request.metadata = metadata;
-        let response = service.reset_user_password(request);
+        *request.metadata_mut() = metadata.clone();
+        let response = service.reset_user_password(request).await;
         assert!(response.is_ok());
 
-        let request =
-            UserLoginRequest::new("test_reset_user_password_id", response.unwrap().password)
-                .into_request();
-        let response = service.user_login(request);
+        let request = UserLoginRequest::new(
+            "test_reset_user_password_id",
+            response.unwrap().into_inner().password,
+        )
+        .into_request();
+        let response = service.user_login(request).await;
         assert!(response.is_ok());
     }
 
-    pub fn test_delete_user() {
+    pub async fn test_delete_user() {
         let service = get_mock_service();
 
         let request = UserLoginRequest::new("admin", "teaclave").into_request();
-        let response = service.user_login(request).unwrap();
+        let response = service.user_login(request).await.unwrap().into_inner();
 
-        let mut metadata = HashMap::new();
-        metadata.insert("id".to_owned(), "admin".to_owned());
-        metadata.insert("token".to_owned(), response.token);
+        let mut metadata = MetadataMap::new();
+        metadata.insert("id", "admin".parse().unwrap());
+        metadata.insert("token", response.token.parse().unwrap());
 
         let mut request =
             UserRegisterRequest::new("test_delete_user_id", "test_password", "FunctionOwner", "")
                 .into_request();
-        request.metadata = metadata;
-        assert!(service.user_register(request).is_ok());
+        *request.metadata_mut() = metadata;
+        assert!(service.user_register(request).await.is_ok());
 
         let request = UserLoginRequest::new("test_delete_user_id", "test_password").into_request();
-        let response = service.user_login(request);
+        let response = service.user_login(request).await;
         assert!(response.is_ok());
 
-        let token = response.unwrap().token;
-        let user = service.db_client.get_user("test_delete_user_id").unwrap();
+        let token = response.unwrap().into_inner().token;
+        let user = service
+            .db_client
+            .lock()
+            .unwrap()
+            .get_user("test_delete_user_id")
+            .unwrap();
         assert!(user.validate_token(&service.jwt_secret, &token).is_ok());
 
         let request = UserLoginRequest::new("admin", "teaclave").into_request();
-        let response = service.user_login(request).unwrap();
-        let mut metadata = HashMap::new();
-        metadata.insert("id".to_owned(), "admin".to_owned());
-        metadata.insert("token".to_owned(), response.token);
+        let response = service.user_login(request).await.unwrap().into_inner();
+        let mut metadata = MetadataMap::new();
+        metadata.insert("id", "admin".parse().unwrap());
+        metadata.insert("token", response.token.parse().unwrap());
         let mut request = DeleteUserRequest::new("test_delete_user_id").into_request();
-        request.metadata = metadata;
-        assert!(service.delete_user(request).is_ok());
+        *request.metadata_mut() = metadata;
+        assert!(service.delete_user(request).await.is_ok());
 
         debug!("saved user_info: {:?}", user);
         let request = UserLoginRequest::new("test_delete_user_id", "test_password").into_request();
-        assert!(service.user_login(request).is_err());
+        assert!(service.user_login(request).await.is_err());
     }
 }
diff --git a/services/authentication/enclave/src/error.rs b/services/authentication/enclave/src/error.rs
index d276fca..b8d34af 100644
--- a/services/authentication/enclave/src/error.rs
+++ b/services/authentication/enclave/src/error.rs
@@ -15,7 +15,6 @@
 // specific language governing permissions and limitations
 // under the License.
 
-use teaclave_types::TeaclaveServiceResponseError;
 use thiserror::Error;
 
 #[derive(Error, Debug)]
@@ -40,11 +39,9 @@
     }
 }
 
-impl From<AuthenticationError> for TeaclaveServiceResponseError {
+impl From<AuthenticationError> for teaclave_rpc::Status {
     fn from(error: AuthenticationError) -> Self {
-        TeaclaveServiceResponseError::RequestError(
-            AuthenticationServiceError::from(error).to_string(),
-        )
+        teaclave_rpc::Status::unauthenticated(AuthenticationServiceError::from(error).to_string())
     }
 }
 
@@ -68,9 +65,9 @@
     MissingToken,
 }
 
-impl From<AuthenticationServiceError> for TeaclaveServiceResponseError {
+impl From<AuthenticationServiceError> for teaclave_rpc::Status {
     fn from(error: AuthenticationServiceError) -> Self {
         log::debug!("AuthenticationServiceError: {:?}", error);
-        TeaclaveServiceResponseError::RequestError(error.to_string())
+        teaclave_rpc::Status::unauthenticated(error.to_string())
     }
 }
diff --git a/services/authentication/enclave/src/internal_service.rs b/services/authentication/enclave/src/internal_service.rs
index b3fbb65..3d26fcf 100644
--- a/services/authentication/enclave/src/internal_service.rs
+++ b/services/authentication/enclave/src/internal_service.rs
@@ -18,49 +18,50 @@
 use crate::error::AuthenticationError;
 use crate::user_db::DbClient;
 use crate::user_info::UserInfo;
+use std::sync::{Arc, Mutex};
 use teaclave_proto::teaclave_authentication_service::{
     TeaclaveAuthenticationInternal, UserAuthenticateRequest, UserAuthenticateResponse,
 };
-use teaclave_rpc::Request;
-use teaclave_service_enclave_utils::{bail, teaclave_service};
+use teaclave_rpc::{ensure, Request, Response};
+use teaclave_service_enclave_utils::bail;
 use teaclave_types::TeaclaveServiceResponseResult;
-
-#[teaclave_service(teaclave_authentication_service, TeaclaveAuthenticationInternal)]
 #[derive(Clone)]
 pub(crate) struct TeaclaveAuthenticationInternalService {
-    db_client: DbClient,
+    db_client: Arc<Mutex<DbClient>>,
     jwt_secret: Vec<u8>,
 }
 
 impl TeaclaveAuthenticationInternalService {
     pub(crate) fn new(db_client: DbClient, jwt_secret: Vec<u8>) -> Self {
         Self {
-            db_client,
+            db_client: Arc::new(Mutex::new(db_client)),
             jwt_secret,
         }
     }
 }
 
+#[teaclave_rpc::async_trait]
 impl TeaclaveAuthenticationInternal for TeaclaveAuthenticationInternalService {
-    fn user_authenticate(
+    async fn user_authenticate(
         &self,
         request: Request<UserAuthenticateRequest>,
     ) -> TeaclaveServiceResponseResult<UserAuthenticateResponse> {
-        let request = request.message;
-        if request.credential.id.is_empty() {
-            bail!(AuthenticationError::InvalidUserId);
-        }
-        if request.credential.token.is_empty() {
-            bail!(AuthenticationError::InvalidToken);
-        }
-        let user: UserInfo = match self.db_client.get_user(&request.credential.id) {
+        let request = request.into_inner();
+        ensure!(
+            request.credential.is_some(),
+            AuthenticationError::IncorrectToken
+        );
+        let cred = request.credential.unwrap();
+        ensure!(!cred.id.is_empty(), AuthenticationError::InvalidUserId);
+        ensure!(!cred.token.is_empty(), AuthenticationError::InvalidToken);
+        let user: UserInfo = match self.db_client.lock().unwrap().get_user(&cred.id) {
             Ok(value) => value,
             Err(_) => bail!(AuthenticationError::InvalidUserId),
         };
         let claims = user
-            .validate_token(&self.jwt_secret, &request.credential.token)
+            .validate_token(&self.jwt_secret, &cred.token)
             .map_err(|_| AuthenticationError::IncorrectToken)?;
-        Ok(UserAuthenticateResponse { claims })
+        Ok(Response::new(UserAuthenticateResponse::new(claims)))
     }
 }
 
@@ -90,27 +91,27 @@
         );
         database.get_client().create_user(&user).unwrap();
         TeaclaveAuthenticationInternalService {
-            db_client: database.get_client(),
+            db_client: Arc::new(Mutex::new(database.get_client())),
             jwt_secret,
         }
     }
 
-    pub fn test_user_authenticate() {
+    pub async fn test_user_authenticate() {
         let id = "test_authenticate_id";
         let service = get_mock_service();
-        let user = service.db_client.get_user(id).unwrap();
+        let user = service.db_client.lock().unwrap().get_user(id).unwrap();
 
         let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
         let exp = (now + Duration::from_secs(24 * 60 * 60)).as_secs(); // 1 day
         let token = user.get_token(exp, &service.jwt_secret).unwrap();
 
-        let response = get_authenticate_response(id, &token, &service);
+        let response = get_authenticate_response(id, &token, &service).await;
         assert!(response.is_ok());
         let token = validate_token(id, &service.jwt_secret, &token);
         debug!("valid token: {:?}", token.unwrap());
     }
 
-    pub fn test_invalid_algorithm() {
+    pub async fn test_invalid_algorithm() {
         let id = "test_authenticate_id";
         let service = get_mock_service();
         let my_claims = get_correct_claim(id);
@@ -119,7 +120,7 @@
             Some(jsonwebtoken::Algorithm::HS256),
             &service.jwt_secret,
         );
-        let response = get_authenticate_response(id, &token, &service);
+        let response = get_authenticate_response(id, &token, &service).await;
         assert!(response.is_err());
         let error = validate_token(id, &service.jwt_secret, &token);
         assert!(error.is_err());
@@ -129,13 +130,13 @@
         }
     }
 
-    pub fn test_invalid_issuer() {
+    pub async fn test_invalid_issuer() {
         let id = "test_authenticate_id";
         let service = get_mock_service();
         let mut my_claims = get_correct_claim(id);
         my_claims.iss = "wrong issuer".to_string();
         let token = gen_token(my_claims, None, &service.jwt_secret);
-        let response = get_authenticate_response(id, &token, &service);
+        let response = get_authenticate_response(id, &token, &service).await;
         assert!(response.is_err());
         let error = validate_token(id, &service.jwt_secret, &token);
         assert!(error.is_err());
@@ -145,13 +146,13 @@
         }
     }
 
-    pub fn test_expired_token() {
+    pub async fn test_expired_token() {
         let id = "test_authenticate_id";
         let service = get_mock_service();
         let mut my_claims = get_correct_claim(id);
         my_claims.exp -= 24 * 60 + 1;
         let token = gen_token(my_claims, None, &service.jwt_secret);
-        let response = get_authenticate_response(id, &token, &service);
+        let response = get_authenticate_response(id, &token, &service).await;
         assert!(response.is_err());
         let error = validate_token(id, &service.jwt_secret, &token);
         assert!(error.is_err());
@@ -161,14 +162,14 @@
         }
     }
 
-    pub fn test_invalid_user() {
+    pub async fn test_invalid_user() {
         let id = "test_authenticate_id";
         let service = get_mock_service();
         let mut my_claims = get_correct_claim(id);
         my_claims.sub = "wrong user".to_string();
         my_claims.role = UserRole::PlatformAdmin.to_string();
         let token = gen_token(my_claims, None, &service.jwt_secret);
-        let response = get_authenticate_response(id, &token, &service);
+        let response = get_authenticate_response(id, &token, &service).await;
         assert!(response.is_err());
         let error = validate_token(id, &service.jwt_secret, &token);
         assert!(error.is_err());
@@ -178,12 +179,12 @@
         }
     }
 
-    pub fn test_wrong_secret() {
+    pub async fn test_wrong_secret() {
         let id = "test_authenticate_id";
         let service = get_mock_service();
         let my_claims = get_correct_claim(id);
         let token = gen_token(my_claims, None, b"bad secret");
-        let response = get_authenticate_response(id, &token, &service);
+        let response = get_authenticate_response(id, &token, &service).await;
         assert!(response.is_err());
         let error = validate_token(id, &service.jwt_secret, &token);
         assert!(error.is_err());
@@ -219,14 +220,14 @@
         jsonwebtoken::encode(&header, &claim, &secret).unwrap()
     }
 
-    fn get_authenticate_response(
+    async fn get_authenticate_response(
         id: &str,
         token: &str,
         service: &TeaclaveAuthenticationInternalService,
     ) -> TeaclaveServiceResponseResult<UserAuthenticateResponse> {
         let credential = UserCredential::new(id, token);
         let request = UserAuthenticateRequest::new(credential).into_request();
-        service.user_authenticate(request)
+        service.user_authenticate(request).await
     }
 
     fn validate_token(
diff --git a/services/authentication/enclave/src/lib.rs b/services/authentication/enclave/src/lib.rs
index 02d8731..921a10a 100644
--- a/services/authentication/enclave/src/lib.rs
+++ b/services/authentication/enclave/src/lib.rs
@@ -22,7 +22,6 @@
 
 use rand::RngCore;
 use std::sync::{Arc, RwLock};
-use std::thread;
 
 use teaclave_attestation::{verifier, AttestationConfig, AttestedTlsConfig, RemoteAttestation};
 use teaclave_binder::proto::{
@@ -35,11 +34,9 @@
 };
 use teaclave_config::RuntimeConfig;
 use teaclave_proto::teaclave_authentication_service::{
-    TeaclaveAuthenticationApiRequest, TeaclaveAuthenticationApiResponse,
-    TeaclaveAuthenticationInternalRequest, TeaclaveAuthenticationInternalResponse,
+    TeaclaveAuthenticationApiServer, TeaclaveAuthenticationInternalServer,
 };
-use teaclave_rpc::config::SgxTrustedTlsServerConfig;
-use teaclave_rpc::server::SgxTrustedTlsServer;
+use teaclave_rpc::{config::SgxTrustedTlsServerConfig, transport::Server};
 use teaclave_service_enclave_utils::{base_dir_for_db, ServiceEnclave};
 use teaclave_types::{EnclaveInfo, TeeServiceError, TeeServiceResult, UserRole};
 
@@ -49,7 +46,7 @@
 mod user_db;
 mod user_info;
 
-fn start_internal_endpoint(
+async fn start_internal_endpoint(
     addr: std::net::SocketAddr,
     db_client: user_db::DbClient,
     jwt_secret: Vec<u8>,
@@ -58,53 +55,42 @@
 ) -> Result<()> {
     let server_config = SgxTrustedTlsServerConfig::from_attested_tls_config(attested_tls_config)?
         .attestation_report_verifier(
-        accepted_enclave_attrs,
-        AS_ROOT_CA_CERT,
-        verifier::universal_quote_verifier,
-    )?;
-
-    let mut server = SgxTrustedTlsServer::<
-        TeaclaveAuthenticationInternalResponse,
-        TeaclaveAuthenticationInternalRequest,
-    >::new(addr, server_config);
-
+            accepted_enclave_attrs,
+            AS_ROOT_CA_CERT,
+            verifier::universal_quote_verifier,
+        )?
+        .into();
     let service =
         internal_service::TeaclaveAuthenticationInternalService::new(db_client, jwt_secret);
-
-    match server.start(service) {
-        Ok(_) => Ok(()),
-        Err(e) => {
-            error!("Service exit, error: {}.", e);
-            Err(anyhow!("cannot start internal endpoint"))
-        }
-    }
+    Server::builder()
+        .tls_config(server_config)
+        .map_err(|_| anyhow!("TeaclaveFrontendServer tls config error"))?
+        .add_service(TeaclaveAuthenticationInternalServer::new(service))
+        .serve(addr)
+        .await?;
+    Ok(())
 }
 
-fn start_api_endpoint(
+async fn start_api_endpoint(
     addr: std::net::SocketAddr,
     db_client: user_db::DbClient,
     jwt_secret: Vec<u8>,
     attested_tls_config: Arc<RwLock<AttestedTlsConfig>>,
 ) -> Result<()> {
-    let server_config = SgxTrustedTlsServerConfig::from_attested_tls_config(attested_tls_config)?;
-
-    let mut server = SgxTrustedTlsServer::<
-        TeaclaveAuthenticationApiResponse,
-        TeaclaveAuthenticationApiRequest,
-    >::new(addr, server_config);
+    let tls_config =
+        SgxTrustedTlsServerConfig::from_attested_tls_config(attested_tls_config)?.into();
 
     let service = api_service::TeaclaveAuthenticationApiService::new(db_client, jwt_secret);
-
-    match server.start(service) {
-        Ok(_) => Ok(()),
-        Err(e) => {
-            error!("Service exit, error: {}.", e);
-            Err(anyhow!("cannot start API endpoint"))
-        }
-    }
+    Server::builder()
+        .tls_config(tls_config)
+        .map_err(|_| anyhow!("TeaclaveAuthenticationApiServer tls config error"))?
+        .add_service(TeaclaveAuthenticationApiServer::new(service))
+        .serve(addr)
+        .await?;
+    Ok(())
 }
 
-fn start_service(config: &RuntimeConfig) -> Result<()> {
+async fn start_service(config: &RuntimeConfig) -> Result<()> {
     info!("Starting Authentication...");
 
     let enclave_info = EnclaveInfo::verify_and_new(
@@ -146,33 +132,30 @@
     }
 
     let client = database.get_client();
-    let api_endpoint_thread_handler = thread::spawn(move || {
-        let _ = start_api_endpoint(
-            api_listen_address,
-            client,
-            api_jwt_secret,
-            attested_tls_config_ref,
-        );
-    });
+    let api_endpoint_thread_handler = tokio::spawn(start_api_endpoint(
+        api_listen_address,
+        client,
+        api_jwt_secret,
+        attested_tls_config_ref,
+    ));
+
     info!(" Starting Authentication: setup API endpoint finished ...");
 
     let client = database.get_client();
-    let internal_endpoint_thread_handler = thread::spawn(move || {
-        let _ = start_internal_endpoint(
-            internal_listen_address,
-            client,
-            internal_jwt_secret,
-            attested_tls_config,
-            accepted_enclave_attrs,
-        );
-    });
+    let internal_endpoint_thread_handler = tokio::spawn(start_internal_endpoint(
+        internal_listen_address,
+        client,
+        internal_jwt_secret,
+        attested_tls_config,
+        accepted_enclave_attrs,
+    ));
     info!(" Starting Authentication: setup Internal endpoint finished ...");
 
-    api_endpoint_thread_handler
-        .join()
+    let _ = api_endpoint_thread_handler
+        .await
         .expect("cannot join API endpoint thread");
-    internal_endpoint_thread_handler
-        .join()
+    let _ = internal_endpoint_thread_handler
+        .await
         .expect("cannot join internal endpoint thread");
 
     info!(" Starting Authentication: start listening ...");
@@ -192,10 +175,16 @@
 
 #[handle_ecall]
 fn handle_start_service(input: &StartServiceInput) -> TeeServiceResult<StartServiceOutput> {
-    match start_service(&input.config) {
+    let result = tokio::runtime::Builder::new_current_thread()
+        .enable_all()
+        .build()
+        .map_err(|_| TeeServiceError::SgxError)?
+        .block_on(start_service(&input.config));
+
+    match result {
         Ok(_) => Ok(StartServiceOutput),
         Err(e) => {
-            log::error!("Failed to start the service: {}", e);
+            error!("Failed to run service: {}", e);
             Err(TeeServiceError::ServiceError)
         }
     }
@@ -226,7 +215,7 @@
     use teaclave_test_utils::*;
 
     pub fn run_tests() -> bool {
-        run_tests!(
+        run_async_tests!(
             api_service::tests::test_user_login,
             api_service::tests::test_user_register,
             api_service::tests::test_user_update,
diff --git a/services/execution/app/Cargo.toml b/services/execution/app/Cargo.toml
index 92e111c..eb41af8 100644
--- a/services/execution/app/Cargo.toml
+++ b/services/execution/app/Cargo.toml
@@ -29,7 +29,8 @@
 libos = [
   "teaclave_execution_service_enclave/libos",
   "teaclave_config/build_config",
-  "teaclave_logger"
+  "teaclave_logger",
+  "tokio"
   ]
 
 [dependencies]
@@ -38,6 +39,7 @@
 libc        = { version = "0.2.66" }
 log         = { version = "0.4.17", features = ["release_max_level_info"] }
 signal-hook = { version = "0.1.13" }
+tokio       = { version = "1.0", features = ["rt-multi-thread", "time", "macros"], optional = true }
 
 teaclave_config                    = { path = "../../../config" }
 teaclave_logger                    = { path = "../../../logger", optional = true }
diff --git a/services/execution/app/src/main.rs b/services/execution/app/src/main.rs
index 10d7a82..7d39ed6 100644
--- a/services/execution/app/src/main.rs
+++ b/services/execution/app/src/main.rs
@@ -28,8 +28,14 @@
     let config_path = "runtime.config.toml";
     let config = teaclave_config::RuntimeConfig::from_toml(config_path)
         .expect("Failed to load config file.");
-    if let Err(e) = teaclave_execution_service_enclave::start_service(&config) {
-        log::error!("app will exit, error {:?}", e);
+    let result = tokio::runtime::Builder::new_multi_thread()
+        .worker_threads(8)
+        .enable_all()
+        .build()
+        .expect("failed to create tokio runtime")
+        .block_on(teaclave_execution_service_enclave::start_service(&config));
+    if result.is_err() {
+        log::error!("app will exit, error {:?}", result);
     }
 }
 
diff --git a/services/execution/enclave/Cargo.toml b/services/execution/enclave/Cargo.toml
index 7600e53..967ad8c 100644
--- a/services/execution/enclave/Cargo.toml
+++ b/services/execution/enclave/Cargo.toml
@@ -48,7 +48,7 @@
   "teaclave_crypto/app",
   "teaclave_file_agent",
   "teaclave_proto/app",
-  "teaclave_rpc/app",
+  "teaclave_rpc/libos",
   "teaclave_service_enclave_utils/libos",
   "teaclave_types/app",
   "teaclave_worker/app",
@@ -62,6 +62,7 @@
 serde_json    = { version = "1.0.39" }
 serde         = { version = "1.0.92", features = ["derive"] }
 thiserror     = { version = "1.0.9" }
+tokio         = { version = "1.0", features = ["rt-multi-thread", "time", "macros"] }
 gbdt          = { version = "0.1.0", features = ["input", "enable_training"] }
 uuid          = { version = "0.8.1", features = ["v4"] }
 url           = { version = "2.1.1", features = ["serde"]}
diff --git a/services/execution/enclave/src/ecall.rs b/services/execution/enclave/src/ecall.rs
index a6a68d2..08cc14d 100644
--- a/services/execution/enclave/src/ecall.rs
+++ b/services/execution/enclave/src/ecall.rs
@@ -25,11 +25,16 @@
 
 #[handle_ecall]
 fn handle_start_service(input: &StartServiceInput) -> TeeServiceResult<StartServiceOutput> {
-    match super::start_service(&input.config) {
+    let result = tokio::runtime::Builder::new_current_thread()
+        .enable_all()
+        .build()
+        .map_err(|_| TeeServiceError::SgxError)?
+        .block_on(super::start_service(&input.config));
+
+    match result {
         Ok(_) => Ok(StartServiceOutput),
-        // terminate the enclave for executor
         Err(e) => {
-            log::error!("Service shutdown, reason: {}", e);
+            log::error!("Failed to run service: {}", e);
             Err(TeeServiceError::EnclaveForceTermination)
         }
     }
diff --git a/services/execution/enclave/src/lib.rs b/services/execution/enclave/src/lib.rs
index 7f092ce..40ef4a1 100644
--- a/services/execution/enclave/src/lib.rs
+++ b/services/execution/enclave/src/lib.rs
@@ -18,25 +18,24 @@
 #![feature(strict_provenance)]
 
 extern crate sgx_types;
-#[cfg(feature = "mesalock_sgx")]
-use std::untrusted::path::PathEx;
-
 use anyhow::{anyhow, ensure, Result};
 use log::info;
 use teaclave_attestation::{verifier, AttestationConfig, RemoteAttestation};
 use teaclave_config::build::{AS_ROOT_CA_CERT, AUDITOR_PUBLIC_KEYS};
 use teaclave_config::RuntimeConfig;
 use teaclave_service_enclave_utils::create_trusted_scheduler_endpoint;
-
 use teaclave_types::EnclaveInfo;
 
 #[cfg(feature = "mesalock_sgx")]
+use std::untrusted::path::PathEx;
+
+#[cfg(feature = "mesalock_sgx")]
 mod ecall;
 mod file_handler;
 mod service;
 mod task_file_manager;
 
-pub fn start_service(config: &RuntimeConfig) -> Result<()> {
+pub async fn start_service(config: &RuntimeConfig) -> Result<()> {
     info!("Starting Execution...");
 
     let attestation_config = AttestationConfig::from_teaclave_config(config)?;
@@ -77,9 +76,9 @@
 
     info!(" Starting Execution: start ...");
     let mut service =
-        service::TeaclaveExecutionService::new(scheduler_service_endpoint, fusion_base)?;
+        service::TeaclaveExecutionService::new(scheduler_service_endpoint, fusion_base).await?;
 
-    service.start()
+    service.start().await
 }
 
 #[cfg(feature = "enclave_unit_test")]
diff --git a/services/execution/enclave/src/service.rs b/services/execution/enclave/src/service.rs
index 96d470a..ace342a 100644
--- a/services/execution/enclave/src/service.rs
+++ b/services/execution/enclave/src/service.rs
@@ -24,7 +24,7 @@
 use crate::task_file_manager::TaskFileManager;
 use teaclave_proto::teaclave_common::{ExecutorCommand, ExecutorStatus};
 use teaclave_proto::teaclave_scheduler_service::*;
-use teaclave_rpc::endpoint::Endpoint;
+use teaclave_rpc::transport::{channel::Endpoint, Channel};
 use teaclave_types::*;
 use teaclave_worker::Worker;
 
@@ -37,30 +37,19 @@
 pub(crate) struct TeaclaveExecutionService {
     #[allow(dead_code)]
     worker: Arc<Worker>,
-    scheduler_client: Arc<Mutex<TeaclaveSchedulerClient>>,
+    scheduler_client: TeaclaveSchedulerClient<Channel>,
     fusion_base: PathBuf,
     id: Uuid,
     status: ExecutorStatus,
 }
 
 impl TeaclaveExecutionService {
-    pub(crate) fn new(
+    pub(crate) async fn new(
         scheduler_service_endpoint: Endpoint,
         fusion_base: impl AsRef<Path>,
     ) -> Result<Self> {
-        let mut i = 0;
-        let channel = loop {
-            match scheduler_service_endpoint.connect() {
-                Ok(channel) => break channel,
-                Err(_) => {
-                    anyhow::ensure!(i < 10, "failed to connect to scheduler service");
-                    log::debug!("Failed to connect to scheduler service, retry {}", i);
-                    i += 1;
-                }
-            }
-            std::thread::sleep(std::time::Duration::from_secs(3));
-        };
-        let scheduler_client = Arc::new(Mutex::new(TeaclaveSchedulerClient::new(channel)?));
+        let channel = scheduler_service_endpoint.connect().await?;
+        let scheduler_client = TeaclaveSchedulerClient::new(channel);
 
         Ok(TeaclaveExecutionService {
             worker: Arc::new(Worker::default()),
@@ -71,7 +60,7 @@
         })
     }
 
-    pub(crate) fn start(&mut self) -> Result<()> {
+    pub(crate) async fn start(&mut self) -> Result<()> {
         let (tx, rx) = mpsc::channel();
         let mut current_task: Arc<Option<StagedTask>> = Arc::new(None);
         let mut task_handle: Option<thread::JoinHandle<()>> = None;
@@ -79,17 +68,17 @@
         loop {
             std::thread::sleep(std::time::Duration::from_secs(3));
 
-            match self.heartbeat() {
+            match self.heartbeat().await {
                 Ok(ExecutorCommand::Stop) => {
                     log::info!("Executor {} is stopped", self.id);
                     return Err(anyhow::anyhow!("EnclaveForceTermination"));
                 }
                 Ok(ExecutorCommand::NewTask) if self.status == ExecutorStatus::Idle => {
-                    match self.pull_task() {
+                    match self.pull_task().await {
                         Ok(task) => {
                             self.status = ExecutorStatus::Executing;
-                            self.update_task_status(&task.task_id, TaskStatus::Running)?;
-                            log::info!("Executor {} accepted a new task, executing...", self.id);
+                            self.update_task_status(&task.task_id, TaskStatus::Running)
+                                .await?;
                             let tx_task = tx.clone();
                             let fusion_base = self.fusion_base.clone();
                             current_task = Arc::new(Some(task));
@@ -132,6 +121,7 @@
                     let task_copy = current_task.clone();
                     match self
                         .update_task_result(&task_copy.as_ref().as_ref().unwrap().task_id, result)
+                        .await
                     {
                         Ok(_) => (),
                         Err(e) => {
@@ -156,62 +146,40 @@
         }
     }
 
-    fn pull_task(&mut self) -> Result<StagedTask> {
+    async fn pull_task(&mut self) -> Result<StagedTask> {
         let request = PullTaskRequest {
-            executor_id: self.id,
+            executor_id: self.id.to_string(),
         };
-        let response = self
-            .scheduler_client
-            .clone()
-            .lock()
-            .map_err(|_| anyhow::anyhow!("Cannot lock scheduler client"))?
-            .pull_task(request)?;
+        let response = self.scheduler_client.pull_task(request).await?.into_inner();
 
         log::debug!("pull_stask response: {:?}", response);
-        Ok(response.staged_task)
+        let staged_task = StagedTask::from_slice(&response.staged_task)?;
+        Ok(staged_task)
     }
 
-    fn heartbeat(&mut self) -> Result<ExecutorCommand> {
-        let request = HeartbeatRequest {
-            executor_id: self.id,
-            status: self.status,
-        };
-        let response = self
-            .scheduler_client
-            .clone()
-            .lock()
-            .map_err(|_| anyhow::anyhow!("Cannot lock scheduler client"))?
-            .heartbeat(request)?;
+    async fn heartbeat(&mut self) -> Result<ExecutorCommand> {
+        let request = HeartbeatRequest::new(self.id, self.status);
+        let response = self.scheduler_client.heartbeat(request).await?.into_inner();
 
         log::debug!("heartbeat_with_result response: {:?}", response);
-        Ok(response.command)
+        response.command.try_into()
     }
 
-    fn update_task_result(
+    async fn update_task_result(
         &mut self,
         task_id: &Uuid,
         task_result: Result<TaskOutputs>,
     ) -> Result<()> {
         let request = UpdateTaskResultRequest::new(*task_id, task_result);
 
-        let _response = self
-            .scheduler_client
-            .clone()
-            .lock()
-            .map_err(|_| anyhow::anyhow!("Cannot lock scheduler client"))?
-            .update_task_result(request)?;
+        let _response = self.scheduler_client.update_task_result(request).await?;
 
         Ok(())
     }
 
-    fn update_task_status(&mut self, task_id: &Uuid, task_status: TaskStatus) -> Result<()> {
+    async fn update_task_status(&mut self, task_id: &Uuid, task_status: TaskStatus) -> Result<()> {
         let request = UpdateTaskStatusRequest::new(task_id.to_owned(), task_status);
-        let _response = self
-            .scheduler_client
-            .clone()
-            .lock()
-            .map_err(|_| anyhow::anyhow!("Cannot lock scheduler client"))?
-            .update_task_status(request)?;
+        let _response = self.scheduler_client.update_task_status(request).await?;
 
         Ok(())
     }
diff --git a/services/frontend/enclave/Cargo.toml b/services/frontend/enclave/Cargo.toml
index b98e17a..ad2c21b 100644
--- a/services/frontend/enclave/Cargo.toml
+++ b/services/frontend/enclave/Cargo.toml
@@ -43,14 +43,15 @@
 enclave_unit_test = ["teaclave_binder/enclave_unit_test", "teaclave_test_utils/mesalock_sgx"]
 
 [dependencies]
-anyhow    = { version = "1.0.26" }
-cfg-if    = { version = "0.1.9" }
-log       = { version = "0.4.17", features = ["release_max_level_info"] }
-serde     = { version = "1.0.92" }
+anyhow     = { version = "1.0.26" }
+cfg-if     = { version = "0.1.9" }
+log        = { version = "0.4.17", features = ["release_max_level_info"] }
+serde      = { version = "1.0.92" }
 serde_json = { version = "1.0.39" }
-thiserror = { version = "1.0.9" }
-ring      = { version = "0.16.5" }
-rand      = { version = "0.8.5" }
+thiserror  = { version = "1.0.9" }
+tokio      = { version = "1.0", features = ["rt-multi-thread", "time", "macros"] }
+ring       = { version = "0.16.5" }
+rand       = { version = "0.8.5" }
 
 teaclave_attestation           = { path = "../../../attestation" }
 teaclave_config                = { path = "../../../config" }
diff --git a/services/frontend/enclave/src/error.rs b/services/frontend/enclave/src/error.rs
index 54264e2..fc8248d 100644
--- a/services/frontend/enclave/src/error.rs
+++ b/services/frontend/enclave/src/error.rs
@@ -15,7 +15,6 @@
 // specific language governing permissions and limitations
 // under the License.
 
-use teaclave_types::TeaclaveServiceResponseError;
 use thiserror::Error;
 
 #[derive(Error, Debug)]
@@ -44,9 +43,17 @@
     Authentication(AuthenticationError),
 }
 
-impl From<FrontendServiceError> for TeaclaveServiceResponseError {
+impl From<FrontendServiceError> for teaclave_rpc::Status {
     fn from(error: FrontendServiceError) -> Self {
         log::debug!("FrontendServiceError: {:?}", error);
-        TeaclaveServiceResponseError::RequestError(error.to_string())
+        match error {
+            FrontendServiceError::PermissionDenied => {
+                teaclave_rpc::Status::permission_denied("permission denied")
+            }
+            FrontendServiceError::Service(e) => teaclave_rpc::Status::internal(e.to_string()),
+            FrontendServiceError::Authentication(e) => {
+                teaclave_rpc::Status::unauthenticated(e.to_string())
+            }
+        }
     }
 }
diff --git a/services/frontend/enclave/src/lib.rs b/services/frontend/enclave/src/lib.rs
index e8c2f2e..67f6680 100644
--- a/services/frontend/enclave/src/lib.rs
+++ b/services/frontend/enclave/src/lib.rs
@@ -29,11 +29,8 @@
 use teaclave_binder::{handle_ecall, register_ecall_handler};
 use teaclave_config::build::AS_ROOT_CA_CERT;
 use teaclave_config::RuntimeConfig;
-use teaclave_proto::teaclave_frontend_service::{
-    TeaclaveFrontendRequest, TeaclaveFrontendResponse,
-};
-use teaclave_rpc::config::SgxTrustedTlsServerConfig;
-use teaclave_rpc::server::SgxTrustedTlsServer;
+use teaclave_proto::teaclave_frontend_service::TeaclaveFrontendServer;
+use teaclave_rpc::{config::SgxTrustedTlsServerConfig, transport::Server};
 use teaclave_service_enclave_utils::{
     create_trusted_authentication_endpoint, create_trusted_management_endpoint, ServiceEnclave,
 };
@@ -42,7 +39,10 @@
 mod error;
 mod service;
 
-fn start_service(config: &RuntimeConfig) -> Result<()> {
+// Sets the number of worker threads the Runtime will use.
+const N_WORKERS: usize = 8;
+
+async fn start_service(config: &RuntimeConfig) -> Result<()> {
     info!("Starting FrontEnd ...");
 
     let listen_address = config.api_endpoints.frontend.listen_address;
@@ -55,12 +55,7 @@
     info!(" Starting FrontEnd: Self attestation finished ...");
 
     let server_config =
-        SgxTrustedTlsServerConfig::from_attested_tls_config(attested_tls_config.clone())?;
-    let mut server = SgxTrustedTlsServer::<TeaclaveFrontendResponse, TeaclaveFrontendRequest>::new(
-        listen_address,
-        server_config,
-    );
-
+        SgxTrustedTlsServerConfig::from_attested_tls_config(attested_tls_config.clone())?.into();
     info!(" Starting FrontEnd: Server config setup finished ...");
 
     let enclave_info = teaclave_types::EnclaveInfo::from_bytes(&config.audit.enclave_info_bytes);
@@ -87,24 +82,32 @@
     let service = service::TeaclaveFrontendService::new(
         authentication_service_endpoint,
         management_service_endpoint,
-    )?;
+    )
+    .await?;
 
     info!(" Starting FrontEnd: start listening ...");
-    match server.start(service) {
-        Ok(_) => (),
-        Err(e) => {
-            error!("Service exit, error: {}.", e);
-        }
-    }
+    Server::builder()
+        .tls_config(server_config)
+        .map_err(|_| anyhow!("TeaclaveFrontendServer tls config error"))?
+        .add_service(TeaclaveFrontendServer::new(service))
+        .serve(listen_address)
+        .await?;
     Ok(())
 }
 
 #[handle_ecall]
 fn handle_start_service(input: &StartServiceInput) -> TeeServiceResult<StartServiceOutput> {
-    match start_service(&input.config) {
+    let result = tokio::runtime::Builder::new_multi_thread()
+        .worker_threads(N_WORKERS)
+        .enable_all()
+        .build()
+        .map_err(|_| TeeServiceError::SgxError)?
+        .block_on(start_service(&input.config));
+
+    match result {
         Ok(_) => Ok(StartServiceOutput),
         Err(e) => {
-            log::error!("Failed to start the service: {}", e);
+            error!("Failed to run service: {}", e);
             Err(TeeServiceError::ServiceError)
         }
     }
diff --git a/services/frontend/enclave/src/service.rs b/services/frontend/enclave/src/service.rs
index bc07276..d2ac9b2 100644
--- a/services/frontend/enclave/src/service.rs
+++ b/services/frontend/enclave/src/service.rs
@@ -18,11 +18,8 @@
 use crate::error::AuthenticationError;
 use crate::error::FrontendServiceError;
 
-use anyhow::anyhow;
-use anyhow::ensure;
-use anyhow::Result;
-use std::sync::{Arc, Mutex};
-
+use anyhow::{anyhow, Result};
+use std::sync::Arc;
 use teaclave_proto::teaclave_authentication_service::{
     TeaclaveAuthenticationInternalClient, UserAuthenticateRequest,
 };
@@ -42,21 +39,21 @@
     UpdateOutputFileRequest, UpdateOutputFileResponse,
 };
 use teaclave_proto::teaclave_management_service::TeaclaveManagementClient;
-use teaclave_rpc::endpoint::Endpoint;
+use teaclave_rpc::transport::{channel::Endpoint, Channel};
 use teaclave_rpc::Request;
-use teaclave_service_enclave_utils::{bail, teaclave_service};
+use teaclave_service_enclave_utils::bail;
 use teaclave_types::{TeaclaveServiceResponseResult, UserAuthClaims, UserRole};
+use tokio::sync::Mutex;
 
-#[teaclave_service(teaclave_frontend_service, TeaclaveFrontend, FrontendServiceError)]
 #[derive(Clone)]
 pub(crate) struct TeaclaveFrontendService {
-    authentication_client: Arc<Mutex<TeaclaveAuthenticationInternalClient>>,
-    management_client: Arc<Mutex<TeaclaveManagementClient>>,
+    authentication_client: Arc<Mutex<TeaclaveAuthenticationInternalClient<Channel>>>,
+    management_client: Arc<Mutex<TeaclaveManagementClient<Channel>>>,
 }
 
 macro_rules! authentication_and_forward_to_management {
     ($service: ident, $request: ident, $func: ident, $endpoint: expr) => {{
-        let claims = match $service.authenticate(&$request) {
+        let claims = match $service.authenticate(&$request).await {
             Ok(claims) => {
                 if authorize(&claims, $endpoint) {
                     claims
@@ -80,19 +77,16 @@
         };
 
         let client = $service.management_client.clone();
-        let mut client = client.lock().map_err(|_| {
-            FrontendServiceError::Service(anyhow!("failed to lock management client"))
-        })?;
-        client.metadata_mut().clear();
-        client.metadata_mut().extend($request.metadata);
-        client
-            .metadata_mut()
-            .insert("role".to_string(), claims.role);
+        let mut client = client.lock().await;
+        let meta = $request.metadata().clone();
+        let message = $request.get_ref().to_owned();
 
-        let response = client.$func($request.message);
+        let mut request = Request::new(message);
+        let metadata = request.metadata_mut();
+        *metadata = meta;
+        metadata.insert("role", claims.role.parse().unwrap());
 
-        client.metadata_mut().clear();
-        let response = response?;
+        let response = client.$func(request).await?;
         Ok(response)
     }};
 }
@@ -157,41 +151,25 @@
 }
 
 impl TeaclaveFrontendService {
-    pub(crate) fn new(
+    pub(crate) async fn new(
         authentication_service_endpoint: Endpoint,
         management_service_endpoint: Endpoint,
     ) -> Result<Self> {
-        let mut i = 0;
-        let authentication_channel = loop {
-            match authentication_service_endpoint.connect() {
-                Ok(channel) => break channel,
-                Err(_) => {
-                    ensure!(i < 10, "failed to connect to authentication service");
-                    log::warn!("Failed to connect to authentication service, retry {}", i);
-                    i += 1;
-                }
-            }
-            std::thread::sleep(std::time::Duration::from_secs(3));
-        };
+        let authentication_channel = authentication_service_endpoint
+            .connect()
+            .await
+            .map_err(|e| anyhow!("Failed to connect to authentication service, retry {:?}", e))?;
         let authentication_client = Arc::new(Mutex::new(
-            TeaclaveAuthenticationInternalClient::new(authentication_channel)?,
+            TeaclaveAuthenticationInternalClient::new(authentication_channel),
         ));
 
-        let mut i = 0;
-        let management_channel = loop {
-            match management_service_endpoint.connect() {
-                Ok(channel) => break channel,
-                Err(_) => {
-                    ensure!(i < 10, "failed to connect to management service");
-                    log::warn!("Failed to connect to management service, retry {}", i);
-                    i += 1;
-                }
-            }
-            std::thread::sleep(std::time::Duration::from_secs(3));
-        };
+        let management_channel = management_service_endpoint
+            .connect()
+            .await
+            .map_err(|e| anyhow!("Failed to connect to management service, {:?}", e))?;
         let management_client = Arc::new(Mutex::new(TeaclaveManagementClient::new(
             management_channel,
-        )?));
+        )));
 
         Ok(Self {
             authentication_client,
@@ -200,8 +178,9 @@
     }
 }
 
+#[teaclave_rpc::async_trait]
 impl TeaclaveFrontend for TeaclaveFrontendService {
-    fn register_input_file(
+    async fn register_input_file(
         &self,
         request: Request<RegisterInputFileRequest>,
     ) -> TeaclaveServiceResponseResult<RegisterInputFileResponse> {
@@ -213,7 +192,7 @@
         )
     }
 
-    fn update_input_file(
+    async fn update_input_file(
         &self,
         request: Request<UpdateInputFileRequest>,
     ) -> TeaclaveServiceResponseResult<UpdateInputFileResponse> {
@@ -225,7 +204,7 @@
         )
     }
 
-    fn register_output_file(
+    async fn register_output_file(
         &self,
         request: Request<RegisterOutputFileRequest>,
     ) -> TeaclaveServiceResponseResult<RegisterOutputFileResponse> {
@@ -237,7 +216,7 @@
         )
     }
 
-    fn update_output_file(
+    async fn update_output_file(
         &self,
         request: Request<UpdateOutputFileRequest>,
     ) -> TeaclaveServiceResponseResult<UpdateOutputFileResponse> {
@@ -249,7 +228,7 @@
         )
     }
 
-    fn register_fusion_output(
+    async fn register_fusion_output(
         &self,
         request: Request<RegisterFusionOutputRequest>,
     ) -> TeaclaveServiceResponseResult<RegisterFusionOutputResponse> {
@@ -261,7 +240,7 @@
         )
     }
 
-    fn register_input_from_output(
+    async fn register_input_from_output(
         &self,
         request: Request<RegisterInputFromOutputRequest>,
     ) -> TeaclaveServiceResponseResult<RegisterInputFromOutputResponse> {
@@ -273,7 +252,7 @@
         )
     }
 
-    fn get_output_file(
+    async fn get_output_file(
         &self,
         request: Request<GetOutputFileRequest>,
     ) -> TeaclaveServiceResponseResult<GetOutputFileResponse> {
@@ -285,7 +264,7 @@
         )
     }
 
-    fn get_input_file(
+    async fn get_input_file(
         &self,
         request: Request<GetInputFileRequest>,
     ) -> TeaclaveServiceResponseResult<GetInputFileResponse> {
@@ -297,7 +276,7 @@
         )
     }
 
-    fn register_function(
+    async fn register_function(
         &self,
         request: Request<RegisterFunctionRequest>,
     ) -> TeaclaveServiceResponseResult<RegisterFunctionResponse> {
@@ -309,7 +288,7 @@
         )
     }
 
-    fn update_function(
+    async fn update_function(
         &self,
         request: Request<UpdateFunctionRequest>,
     ) -> TeaclaveServiceResponseResult<UpdateFunctionResponse> {
@@ -321,7 +300,7 @@
         )
     }
 
-    fn get_function(
+    async fn get_function(
         &self,
         request: Request<GetFunctionRequest>,
     ) -> TeaclaveServiceResponseResult<GetFunctionResponse> {
@@ -333,7 +312,7 @@
         )
     }
 
-    fn get_function_usage_stats(
+    async fn get_function_usage_stats(
         &self,
         request: Request<GetFunctionUsageStatsRequest>,
     ) -> TeaclaveServiceResponseResult<GetFunctionUsageStatsResponse> {
@@ -345,7 +324,7 @@
         )
     }
 
-    fn delete_function(
+    async fn delete_function(
         &self,
         request: Request<DeleteFunctionRequest>,
     ) -> TeaclaveServiceResponseResult<DeleteFunctionResponse> {
@@ -357,7 +336,7 @@
         )
     }
 
-    fn disable_function(
+    async fn disable_function(
         &self,
         request: Request<DisableFunctionRequest>,
     ) -> TeaclaveServiceResponseResult<DisableFunctionResponse> {
@@ -369,7 +348,7 @@
         )
     }
 
-    fn list_functions(
+    async fn list_functions(
         &self,
         request: Request<ListFunctionsRequest>,
     ) -> TeaclaveServiceResponseResult<ListFunctionsResponse> {
@@ -381,28 +360,28 @@
         )
     }
 
-    fn create_task(
+    async fn create_task(
         &self,
         request: Request<CreateTaskRequest>,
     ) -> TeaclaveServiceResponseResult<CreateTaskResponse> {
         authentication_and_forward_to_management!(self, request, create_task, Endpoints::CreateTask)
     }
 
-    fn get_task(
+    async fn get_task(
         &self,
         request: Request<GetTaskRequest>,
     ) -> TeaclaveServiceResponseResult<GetTaskResponse> {
         authentication_and_forward_to_management!(self, request, get_task, Endpoints::GetTask)
     }
 
-    fn assign_data(
+    async fn assign_data(
         &self,
         request: Request<AssignDataRequest>,
     ) -> TeaclaveServiceResponseResult<AssignDataResponse> {
         authentication_and_forward_to_management!(self, request, assign_data, Endpoints::AssignData)
     }
 
-    fn approve_task(
+    async fn approve_task(
         &self,
         request: Request<ApproveTaskRequest>,
     ) -> TeaclaveServiceResponseResult<ApproveTaskResponse> {
@@ -414,14 +393,14 @@
         )
     }
 
-    fn invoke_task(
+    async fn invoke_task(
         &self,
         request: Request<InvokeTaskRequest>,
     ) -> TeaclaveServiceResponseResult<InvokeTaskResponse> {
         authentication_and_forward_to_management!(self, request, invoke_task, Endpoints::InvokeTask)
     }
 
-    fn cancel_task(
+    async fn cancel_task(
         &self,
         request: Request<CancelTaskRequest>,
     ) -> TeaclaveServiceResponseResult<CancelTaskResponse> {
@@ -430,30 +409,34 @@
 }
 
 impl TeaclaveFrontendService {
-    fn authenticate<T>(
+    async fn authenticate<T>(
         &self,
         request: &Request<T>,
     ) -> Result<UserAuthClaims, FrontendServiceError> {
         let id = request
-            .metadata
+            .metadata()
             .get("id")
+            .and_then(|x| x.to_str().ok())
             .ok_or(AuthenticationError::MissingUserId)?;
         let token = request
-            .metadata
+            .metadata()
             .get("token")
+            .and_then(|x| x.to_str().ok())
             .ok_or(AuthenticationError::MissingToken)?;
-        let credential = UserCredential::new(id, token);
+        let credential = Some(UserCredential::new(id, token));
         let auth_request = UserAuthenticateRequest { credential };
         let claims = self
             .authentication_client
             .clone()
             .lock()
-            .map_err(|_| {
-                FrontendServiceError::Service(anyhow!("failed to lock authentication client"))
-            })?
+            .await
             .user_authenticate(auth_request)
+            .await
             .map_err(|_| AuthenticationError::IncorrectCredential)?
-            .claims;
+            .into_inner()
+            .claims
+            .and_then(|x| x.try_into().ok())
+            .ok_or(AuthenticationError::IncorrectCredential)?;
 
         Ok(claims)
     }
diff --git a/services/management/enclave/Cargo.toml b/services/management/enclave/Cargo.toml
index 514b1d7..dbdd744 100644
--- a/services/management/enclave/Cargo.toml
+++ b/services/management/enclave/Cargo.toml
@@ -49,6 +49,7 @@
 serde     = { version = "1.0.92" }
 serde_json = { version = "1.0.39" }
 thiserror = { version = "1.0.9" }
+tokio     = { version = "1.0", features = ["rt-multi-thread", "time", "macros"] }
 ring      = { version = "0.16.5" }
 rand      = { version = "0.8.5" }
 uuid      = { version = "0.8.1", features = ["v4"] }
diff --git a/services/management/enclave/src/error.rs b/services/management/enclave/src/error.rs
index ed33014..33515ef 100644
--- a/services/management/enclave/src/error.rs
+++ b/services/management/enclave/src/error.rs
@@ -15,9 +15,8 @@
 // specific language governing permissions and limitations
 // under the License.
 
-use teaclave_types::TeaclaveServiceResponseError;
+use teaclave_rpc::{Code, Status};
 use thiserror::Error;
-
 #[derive(Error, Debug)]
 pub(crate) enum ManagementServiceError {
     #[error("service internal error")]
@@ -50,9 +49,20 @@
     FunctionQuotaError,
 }
 
-impl From<ManagementServiceError> for TeaclaveServiceResponseError {
+impl From<ManagementServiceError> for Status {
     fn from(error: ManagementServiceError) -> Self {
         log::debug!("ManagementServiceError: {:?}", error);
-        TeaclaveServiceResponseError::RequestError(error.to_string())
+        let msg = error.to_string();
+        let code = match error {
+            ManagementServiceError::PermissionDenied => Code::PermissionDenied,
+            ManagementServiceError::Service(_) => Code::Internal,
+            ManagementServiceError::InvalidDataId
+            | ManagementServiceError::InvalidOutputFile
+            | ManagementServiceError::InvalidFunctionId
+            | ManagementServiceError::InvalidTaskId
+            | ManagementServiceError::InvalidTask => Code::InvalidArgument,
+            _ => Code::Unknown,
+        };
+        Status::new(code, msg)
     }
 }
diff --git a/services/management/enclave/src/lib.rs b/services/management/enclave/src/lib.rs
index 66a4ec0..6faf32f 100644
--- a/services/management/enclave/src/lib.rs
+++ b/services/management/enclave/src/lib.rs
@@ -28,18 +28,17 @@
 use teaclave_binder::{handle_ecall, register_ecall_handler};
 use teaclave_config::build::{AS_ROOT_CA_CERT, AUDITOR_PUBLIC_KEYS, MANAGEMENT_INBOUND_SERVICES};
 use teaclave_config::RuntimeConfig;
-use teaclave_proto::teaclave_management_service::{
-    TeaclaveManagementRequest, TeaclaveManagementResponse,
-};
-use teaclave_rpc::config::SgxTrustedTlsServerConfig;
-use teaclave_rpc::server::SgxTrustedTlsServer;
+use teaclave_proto::teaclave_management_service::TeaclaveManagementServer;
 use teaclave_service_enclave_utils::{create_trusted_storage_endpoint, ServiceEnclave};
 use teaclave_types::{EnclaveInfo, TeeServiceError, TeeServiceResult};
 
 mod error;
 mod service;
 
-fn start_service(config: &RuntimeConfig) -> Result<()> {
+// Sets the number of worker threads the Runtime will use.
+const N_WORKERS: usize = 8;
+
+async fn start_service(config: &RuntimeConfig) -> Result<()> {
     info!("Starting Management...");
 
     let listen_address = config.internal_endpoints.management.listen_address;
@@ -62,22 +61,18 @@
             None => Err(anyhow!("cannot get enclave attribute of {}", service)),
         })
         .collect::<Result<_>>()?;
-    let server_config =
-        SgxTrustedTlsServerConfig::from_attested_tls_config(attested_tls_config.clone())?
-            .attestation_report_verifier(
-                accepted_enclave_attrs,
-                AS_ROOT_CA_CERT,
-                verifier::universal_quote_verifier,
-            )?;
 
+    let server_config = teaclave_rpc::config::SgxTrustedTlsServerConfig::from_attested_tls_config(
+        attested_tls_config.clone(),
+    )?
+    .attestation_report_verifier(
+        accepted_enclave_attrs,
+        AS_ROOT_CA_CERT,
+        verifier::universal_quote_verifier,
+    )?
+    .into();
     info!(" Starting Management: Server config setup finished ...");
 
-    let mut server =
-        SgxTrustedTlsServer::<TeaclaveManagementResponse, TeaclaveManagementRequest>::new(
-            listen_address,
-            server_config,
-        );
-
     let storage_service_endpoint = create_trusted_storage_endpoint(
         &config.internal_endpoints.storage.advertised_address,
         &enclave_info,
@@ -88,24 +83,31 @@
 
     info!(" Starting Management: setup storage endpoint finished ...");
 
-    let service = service::TeaclaveManagementService::new(storage_service_endpoint)?;
+    let service = service::TeaclaveManagementService::new(storage_service_endpoint).await?;
 
     info!(" Starting Management: start listening ...");
-    match server.start(service) {
-        Ok(_) => (),
-        Err(e) => {
-            error!("Service exit, error: {}.", e);
-        }
-    }
+    teaclave_rpc::transport::Server::builder()
+        .tls_config(server_config)
+        .map_err(|_| anyhow::anyhow!("TeaclaveFrontendServer tls config error"))?
+        .add_service(TeaclaveManagementServer::new(service))
+        .serve(listen_address)
+        .await?;
     Ok(())
 }
 
 #[handle_ecall]
 fn handle_start_service(input: &StartServiceInput) -> TeeServiceResult<StartServiceOutput> {
-    match start_service(&input.config) {
+    let result = tokio::runtime::Builder::new_multi_thread()
+        .worker_threads(N_WORKERS)
+        .enable_all()
+        .build()
+        .map_err(|_| TeeServiceError::SgxError)?
+        .block_on(start_service(&input.config));
+
+    match result {
         Ok(_) => Ok(StartServiceOutput),
         Err(e) => {
-            log::error!("Failed to start the service: {}", e);
+            error!("Failed to run service: {}", e);
             Err(TeeServiceError::ServiceError)
         }
     }
diff --git a/services/management/enclave/src/service.rs b/services/management/enclave/src/service.rs
index 2cb4b4f..0abbd12 100644
--- a/services/management/enclave/src/service.rs
+++ b/services/management/enclave/src/service.rs
@@ -18,7 +18,11 @@
 use crate::error::ManagementServiceError;
 use anyhow::anyhow;
 use std::convert::TryInto;
-use std::sync::{Arc, Mutex};
+use std::sync::Arc;
+use teaclave_proto::teaclave_common::i32_from_task_status;
+use teaclave_proto::teaclave_frontend_service::{
+    from_proto_file_ids, from_proto_ownership, to_proto_file_ids, to_proto_ownership,
+};
 use teaclave_proto::teaclave_frontend_service::{
     ApproveTaskRequest, ApproveTaskResponse, AssignDataRequest, AssignDataResponse,
     CancelTaskRequest, CancelTaskResponse, CreateTaskRequest, CreateTaskResponse,
@@ -38,56 +42,57 @@
     DeleteRequest, EnqueueRequest, GetKeysByPrefixRequest, GetRequest, PutRequest,
     TeaclaveStorageClient,
 };
-use teaclave_rpc::endpoint::Endpoint;
-use teaclave_rpc::Request;
-use teaclave_service_enclave_utils::{ensure, teaclave_service};
+use teaclave_rpc::transport::{channel::Endpoint, Channel};
+use teaclave_rpc::{Request, Response};
+use teaclave_service_enclave_utils::ensure;
 use teaclave_types::*;
+use tokio::sync::Mutex;
 use url::Url;
 use uuid::Uuid;
 
-#[teaclave_service(
-    teaclave_management_service,
-    TeaclaveManagement,
-    ManagementServiceError
-)]
 #[derive(Clone)]
 pub(crate) struct TeaclaveManagementService {
-    storage_client: Arc<Mutex<TeaclaveStorageClient>>,
+    storage_client: Arc<Mutex<TeaclaveStorageClient<Channel>>>,
 }
 
+#[teaclave_rpc::async_trait]
 impl TeaclaveManagement for TeaclaveManagementService {
     // access control: none
-    fn register_input_file(
+    async fn register_input_file(
         &self,
         request: Request<RegisterInputFileRequest>,
     ) -> TeaclaveServiceResponseResult<RegisterInputFileResponse> {
         let user_id = get_request_user_id(&request)?;
-        let request = request.message;
-        let input_file = TeaclaveInputFile::new(
-            request.url,
-            request.cmac,
-            request.crypto_info,
-            vec![user_id],
-        );
+        let request = request.into_inner();
+        let url = Url::parse(&request.url).map_err(tonic_error)?;
+        let cmac = FileAuthTag::from_bytes(&request.cmac).map_err(tonic_error)?;
+        let crypto_info = request
+            .crypto_info
+            .ok_or_else(|| tonic_error("missing crypto_info"))?
+            .try_into()
+            .map_err(tonic_error)?;
 
-        self.write_to_db(&input_file)?;
+        let input_file = TeaclaveInputFile::new(url, cmac, crypto_info, vec![user_id]);
+
+        self.write_to_db(&input_file).await?;
 
         let response = RegisterInputFileResponse::new(input_file.external_id());
-        Ok(response)
+        Ok(Response::new(response))
     }
 
     // access control:
     // 1) exisiting_file.owner_list.len() == 1
     // 2) user_id in existing_file.owner_list
-    fn update_input_file(
+    async fn update_input_file(
         &self,
         request: Request<UpdateInputFileRequest>,
     ) -> TeaclaveServiceResponseResult<UpdateInputFileResponse> {
         let user_id = get_request_user_id(&request)?;
-        let request = request.message;
+        let request = request.into_inner();
 
         let old_input_file: TeaclaveInputFile = self
-            .read_from_db(&request.data_id)
+            .read_from_db(&request.data_id.try_into().map_err(tonic_error)?)
+            .await
             .map_err(|_| ManagementServiceError::InvalidDataId)?;
 
         ensure!(
@@ -96,45 +101,54 @@
         );
 
         let input_file = TeaclaveInputFile::new(
-            request.url,
+            Url::parse(&request.url).map_err(tonic_error)?,
             old_input_file.cmac,
             old_input_file.crypto_info,
             old_input_file.owner,
         );
 
-        self.write_to_db(&input_file)?;
+        self.write_to_db(&input_file).await?;
 
         let response = UpdateInputFileResponse::new(input_file.external_id());
-        Ok(response)
+        Ok(Response::new(response))
     }
 
     // access control: none
-    fn register_output_file(
+    async fn register_output_file(
         &self,
         request: Request<RegisterOutputFileRequest>,
     ) -> TeaclaveServiceResponseResult<RegisterOutputFileResponse> {
         let user_id = get_request_user_id(&request)?;
-        let request = request.message;
-        let output_file = TeaclaveOutputFile::new(request.url, request.crypto_info, vec![user_id]);
+        let request = request.into_inner();
+        let output_file = TeaclaveOutputFile::new(
+            Url::parse(&request.url).map_err(tonic_error)?,
+            request
+                .crypto_info
+                .ok_or_else(|| tonic_error("missing crypto_info"))?
+                .try_into()
+                .map_err(tonic_error)?,
+            vec![user_id],
+        );
 
-        self.write_to_db(&output_file)?;
+        self.write_to_db(&output_file).await?;
 
         let response = RegisterOutputFileResponse::new(output_file.external_id());
-        Ok(response)
+        Ok(Response::new(response))
     }
 
     // access control:
     // 1) exisiting_file.owner_list.len() == 1
     // 2) user_id in existing_file.owner_list
-    fn update_output_file(
+    async fn update_output_file(
         &self,
         request: Request<UpdateOutputFileRequest>,
     ) -> TeaclaveServiceResponseResult<UpdateOutputFileResponse> {
         let user_id = get_request_user_id(&request)?;
-        let request = request.message;
+        let request = request.into_inner();
 
         let old_output_file: TeaclaveOutputFile = self
-            .read_from_db(&request.data_id)
+            .read_from_db(&request.data_id.try_into().map_err(tonic_error)?)
+            .await
             .map_err(|_| ManagementServiceError::InvalidDataId)?;
 
         ensure!(
@@ -143,49 +157,54 @@
         );
 
         let output_file = TeaclaveOutputFile::new(
-            request.url,
+            Url::parse(&request.url).map_err(tonic_error)?,
             old_output_file.crypto_info,
             old_output_file.owner,
         );
 
-        self.write_to_db(&output_file)?;
+        self.write_to_db(&output_file).await?;
 
         let response = UpdateOutputFileResponse::new(output_file.external_id());
-        Ok(response)
+        Ok(Response::new(response))
     }
 
     // access control: user_id in owner_list
-    fn register_fusion_output(
+    async fn register_fusion_output(
         &self,
         request: Request<RegisterFusionOutputRequest>,
     ) -> TeaclaveServiceResponseResult<RegisterFusionOutputResponse> {
-        let user_id = get_request_user_id(&request)?;
+        let user_id = get_request_user_id(&request)?.to_string();
 
-        let owner_list = request.message.owner_list;
+        let owner_list = request.into_inner().owner_list;
         ensure!(
             owner_list.len() > 1 && owner_list.contains(&user_id),
             ManagementServiceError::PermissionDenied
         );
 
-        let output_file = create_fusion_data(owner_list)?;
+        let output_file = create_fusion_data(owner_list).map_err(tonic_error)?;
 
-        self.write_to_db(&output_file)?;
+        self.write_to_db(&output_file).await?;
 
         let response = RegisterFusionOutputResponse::new(output_file.external_id());
-        Ok(response)
+        Ok(Response::new(response))
     }
 
     // access control:
     // 1) user_id in output.owner
     // 2) cmac != none
-    fn register_input_from_output(
+    async fn register_input_from_output(
         &self,
         request: Request<RegisterInputFromOutputRequest>,
     ) -> TeaclaveServiceResponseResult<RegisterInputFromOutputResponse> {
         let user_id = get_request_user_id(&request)?;
-
+        let data_id = request
+            .into_inner()
+            .data_id
+            .try_into()
+            .map_err(|_| ManagementServiceError::InvalidDataId)?;
         let output: TeaclaveOutputFile = self
-            .read_from_db(&request.message.data_id)
+            .read_from_db(&data_id)
+            .await
             .map_err(|_| ManagementServiceError::InvalidDataId)?;
 
         ensure!(
@@ -196,21 +215,26 @@
         let input = TeaclaveInputFile::from_output(output)
             .map_err(|_| ManagementServiceError::InvalidOutputFile)?;
 
-        self.write_to_db(&input)?;
+        self.write_to_db(&input).await?;
 
         let response = RegisterInputFromOutputResponse::new(input.external_id());
-        Ok(response)
+        Ok(Response::new(response))
     }
 
     // access control: output_file.owner contains user_id
-    fn get_output_file(
+    async fn get_output_file(
         &self,
         request: Request<GetOutputFileRequest>,
     ) -> TeaclaveServiceResponseResult<GetOutputFileResponse> {
         let user_id = get_request_user_id(&request)?;
-
+        let data_id = request
+            .into_inner()
+            .data_id
+            .try_into()
+            .map_err(|_| ManagementServiceError::InvalidDataId)?;
         let output_file: TeaclaveOutputFile = self
-            .read_from_db(&request.message.data_id)
+            .read_from_db(&data_id)
+            .await
             .map_err(|_| ManagementServiceError::InvalidDataId)?;
 
         ensure!(
@@ -219,18 +243,23 @@
         );
 
         let response = GetOutputFileResponse::new(output_file.owner, output_file.cmac);
-        Ok(response)
+        Ok(Response::new(response))
     }
 
     // access control: input_file.owner contains user_id
-    fn get_input_file(
+    async fn get_input_file(
         &self,
         request: Request<GetInputFileRequest>,
     ) -> TeaclaveServiceResponseResult<GetInputFileResponse> {
         let user_id = get_request_user_id(&request)?;
-
+        let data_id = request
+            .into_inner()
+            .data_id
+            .try_into()
+            .map_err(|_| ManagementServiceError::InvalidDataId)?;
         let input_file: TeaclaveInputFile = self
-            .read_from_db(&request.message.data_id)
+            .read_from_db(&data_id)
+            .await
             .map_err(|_| ManagementServiceError::InvalidDataId)?;
 
         ensure!(
@@ -239,22 +268,23 @@
         );
 
         let response = GetInputFileResponse::new(input_file.owner, input_file.cmac);
-        Ok(response)
+        Ok(Response::new(response))
     }
 
     // access_control: none
-    fn register_function(
+    async fn register_function(
         &self,
         request: Request<RegisterFunctionRequest>,
     ) -> TeaclaveServiceResponseResult<RegisterFunctionResponse> {
         let user_id = get_request_user_id(&request)?;
 
-        let function = FunctionBuilder::from(request.message)
+        let function = FunctionBuilder::try_from(request.into_inner())
+            .map_err(tonic_error)?
             .id(Uuid::new_v4())
             .owner(user_id.clone())
             .build();
 
-        self.write_to_db(&function)?;
+        self.write_to_db(&function).await?;
 
         let mut u = User {
             id: user_id,
@@ -262,17 +292,17 @@
         };
         let external_id = u.external_id();
 
-        let user = self.read_from_db::<User>(&external_id);
+        let user = self.read_from_db::<User>(&external_id).await;
         match user {
             Ok(mut us) => {
                 us.registered_functions
                     .push(function.external_id().to_string());
-                self.write_to_db(&us)?;
+                self.write_to_db(&us).await?;
             }
             Err(_) => {
                 u.registered_functions
                     .push(function.external_id().to_string());
-                self.write_to_db(&u)?;
+                self.write_to_db(&u).await?;
             }
         }
 
@@ -283,16 +313,16 @@
                 ..Default::default()
             };
             let external_id = u.external_id();
-            let user = self.read_from_db::<User>(&external_id);
+            let user = self.read_from_db::<User>(&external_id).await;
             match user {
                 Ok(mut us) => {
                     us.allowed_functions
                         .push(function.external_id().to_string());
-                    self.write_to_db(&us)?;
+                    self.write_to_db(&us).await?;
                 }
                 Err(_) => {
                     u.allowed_functions.push(function.external_id().to_string());
-                    self.write_to_db(&u)?;
+                    self.write_to_db(&u).await?;
                 }
             }
         }
@@ -301,70 +331,76 @@
             function_id: function.id,
             ..Default::default()
         };
-        self.write_to_db(&usage)?;
+        self.write_to_db(&usage).await?;
 
         let response = RegisterFunctionResponse::new(function.external_id());
-        Ok(response)
+        Ok(Response::new(response))
     }
 
-    fn update_function(
+    async fn update_function(
         &self,
         request: Request<UpdateFunctionRequest>,
     ) -> TeaclaveServiceResponseResult<UpdateFunctionResponse> {
         let user_id = get_request_user_id(&request)?;
 
-        let function = FunctionBuilder::from(request.message)
+        let function = FunctionBuilder::try_from(request.into_inner())
+            .map_err(tonic_error)?
             .owner(user_id)
             .build();
 
-        self.write_to_db(&function)?;
+        self.write_to_db(&function).await?;
 
         let response = UpdateFunctionResponse::new(function.external_id());
-        Ok(response)
+        Ok(Response::new(response))
     }
 
     // access control: function.public || function.owner == user_id || request.role == PlatformAdmin
-    fn get_function(
+    async fn get_function(
         &self,
         request: Request<GetFunctionRequest>,
     ) -> TeaclaveServiceResponseResult<GetFunctionResponse> {
         let user_id = get_request_user_id(&request)?;
-
-        let function: Function = self
-            .read_from_db(&request.message.function_id)
-            .map_err(|_| ManagementServiceError::InvalidFunctionId)?;
         let role = get_request_role(&request)?;
+        let function_id = request
+            .into_inner()
+            .function_id
+            .try_into()
+            .map_err(|_| ManagementServiceError::InvalidFunctionId)?;
+        let function: Function = self
+            .read_from_db(&function_id)
+            .await
+            .map_err(|_| ManagementServiceError::InvalidFunctionId)?;
 
         if function.public || role == UserRole::PlatformAdmin || function.owner == user_id {
             let response = GetFunctionResponse {
                 name: function.name,
                 description: function.description,
-                owner: function.owner,
-                executor_type: function.executor_type,
+                owner: function.owner.to_string(),
+                executor_type: function.executor_type.to_string(),
                 payload: function.payload,
                 public: function.public,
-                arguments: function.arguments,
-                inputs: function.inputs,
-                outputs: function.outputs,
+                arguments: function.arguments.into_iter().map(|x| x.into()).collect(),
+                inputs: function.inputs.into_iter().map(|x| x.into()).collect(),
+                outputs: function.outputs.into_iter().map(|x| x.into()).collect(),
                 user_allowlist: function.user_allowlist,
             };
 
-            Ok(response)
+            Ok(Response::new(response))
         } else if !function.public && function.user_allowlist.contains(&user_id.into()) {
             let response = GetFunctionResponse {
                 name: function.name,
                 description: function.description,
-                owner: function.owner,
-                executor_type: function.executor_type,
+                owner: function.owner.to_string(),
+                executor_type: function.executor_type.to_string(),
                 payload: vec![],
                 public: function.public,
-                arguments: function.arguments,
-                inputs: function.inputs,
-                outputs: function.outputs,
+                arguments: function.arguments.into_iter().map(|x| x.into()).collect(),
+                inputs: function.inputs.into_iter().map(|x| x.into()).collect(),
+                outputs: function.outputs.into_iter().map(|x| x.into()).collect(),
                 user_allowlist: vec![],
             };
 
-            Ok(response)
+            Ok(Response::new(response))
         } else {
             Err(ManagementServiceError::PermissionDenied.into())
         }
@@ -372,15 +408,20 @@
 
     // access control:
     // function.public || request.role == PlatformAdmin || requested user_id in the user_allowlist
-    fn get_function_usage_stats(
+    async 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_id = request
+            .into_inner()
+            .function_id
+            .try_into()
+            .map_err(|_| ManagementServiceError::InvalidFunctionId)?;
         let function: Function = self
-            .read_from_db(&request.function_id)
+            .read_from_db(&function_id)
+            .await
             .map_err(|_| ManagementServiceError::InvalidFunctionId)?;
 
         ensure!(
@@ -397,49 +438,61 @@
         let external_id = usage.external_id();
         let function_usage = self
             .read_from_db::<FunctionUsage>(&external_id)
+            .await
             .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)
+        Ok(Response::new(response))
     }
 
     // access control: function.owner == user_id
-    fn delete_function(
+    async fn delete_function(
         &self,
         request: Request<DeleteFunctionRequest>,
     ) -> TeaclaveServiceResponseResult<DeleteFunctionResponse> {
         let user_id = get_request_user_id(&request)?;
-
+        let function_id = request
+            .into_inner()
+            .function_id
+            .try_into()
+            .map_err(|_| ManagementServiceError::InvalidFunctionId)?;
         let function: Function = self
-            .read_from_db(&request.message.function_id)
+            .read_from_db(&function_id)
+            .await
             .map_err(|_| ManagementServiceError::InvalidFunctionId)?;
 
         ensure!(
             function.owner == user_id,
             ManagementServiceError::PermissionDenied
         );
-        self.delete_from_db(&request.message.function_id)
+        self.delete_from_db(&function_id)
+            .await
             .map_err(|_| ManagementServiceError::InvalidFunctionId)?;
         let response = DeleteFunctionResponse {};
-        Ok(response)
+        Ok(Response::new(response))
     }
 
     // access control: function.owner == user_id
     // disable function
     // 1. `List functions` does not show this function
     // 2. `Create new task` with the function id fails
-    fn disable_function(
+    async fn disable_function(
         &self,
         request: Request<DisableFunctionRequest>,
     ) -> TeaclaveServiceResponseResult<DisableFunctionResponse> {
         let user_id = get_request_user_id(&request)?;
         let role = get_request_role(&request)?;
-
+        let function_id = request
+            .into_inner()
+            .function_id
+            .try_into()
+            .map_err(|_| ManagementServiceError::InvalidFunctionId)?;
         let mut function: Function = self
-            .read_from_db(&request.message.function_id)
+            .read_from_db(&function_id)
+            .await
             .map_err(|_| ManagementServiceError::InvalidFunctionId)?;
 
         if role != UserRole::PlatformAdmin {
@@ -456,11 +509,11 @@
             ..Default::default()
         };
         let external_id = u.external_id();
-        let user = self.read_from_db::<User>(&external_id);
+        let user = self.read_from_db::<User>(&external_id).await;
         if let Ok(mut us) = user {
             us.allowed_functions.retain(|f| !f.eq(&func_id));
             us.registered_functions.retain(|f| !f.eq(&func_id));
-            self.write_to_db(&us)?;
+            self.write_to_db(&us).await?;
         } else {
             log::warn!("Invalid user id from functions");
         }
@@ -472,28 +525,28 @@
                 ..Default::default()
             };
             let external_id = u.external_id();
-            let user = self.read_from_db::<User>(&external_id);
+            let user = self.read_from_db::<User>(&external_id).await;
             if let Ok(mut us) = user {
                 us.allowed_functions.retain(|f| !f.eq(&func_id));
                 us.registered_functions.retain(|f| !f.eq(&func_id));
-                self.write_to_db(&us)?;
+                self.write_to_db(&us).await?;
             } else {
                 log::warn!("Invalid user id from functions");
             }
         }
 
         function.user_allowlist.clear();
-        self.write_to_db(&function)?;
+        self.write_to_db(&function).await?;
         let response = DisableFunctionResponse {};
-        Ok(response)
+        Ok(Response::new(response))
     }
 
     // access contro: user_id = request.user_id
-    fn list_functions(
+    async fn list_functions(
         &self,
         request: Request<ListFunctionsRequest>,
     ) -> TeaclaveServiceResponseResult<ListFunctionsResponse> {
-        let mut request_user_id = request.message.user_id.clone();
+        let mut request_user_id = request.get_ref().user_id.clone().into();
 
         let current_user_id = get_request_user_id(&request)?;
         let role = get_request_role(&request)?;
@@ -515,7 +568,7 @@
         };
         let external_id = u.external_id();
 
-        let user = self.read_from_db::<User>(&external_id);
+        let user = self.read_from_db::<User>(&external_id).await;
         match user {
             Ok(us) => {
                 let mut response = ListFunctionsResponse {
@@ -523,16 +576,17 @@
                     allowed_functions: us.allowed_functions,
                 };
                 if role == UserRole::PlatformAdmin {
-                    let allowed_functions =
-                        self.get_keys_by_prefix_from_db(Function::key_prefix())?;
+                    let allowed_functions = self
+                        .get_keys_by_prefix_from_db(Function::key_prefix())
+                        .await?;
                     response.allowed_functions = allowed_functions;
                 }
 
-                Ok(response)
+                Ok(Response::new(response))
             }
             Err(_) => {
                 let response = ListFunctionsResponse::default();
-                Ok(response)
+                Ok(Response::new(response))
             }
         }
     }
@@ -543,17 +597,22 @@
     // 2) input files match function definition
     // 3) output files match function definition
     // 4) requested user_id in the user_allowlist
-    fn create_task(
+    async fn create_task(
         &self,
         request: Request<CreateTaskRequest>,
     ) -> TeaclaveServiceResponseResult<CreateTaskResponse> {
         let user_id = get_request_user_id(&request)?;
         let role = get_request_role(&request)?;
 
-        let request = request.message;
+        let request = request.into_inner();
+        let function_id = request
+            .function_id
+            .try_into()
+            .map_err(|_| ManagementServiceError::InvalidFunctionId)?;
 
         let function: Function = self
-            .read_from_db(&request.function_id)
+            .read_from_db(&function_id)
+            .await
             .map_err(|_| ManagementServiceError::InvalidFunctionId)?;
 
         match role {
@@ -570,31 +629,36 @@
         }
         let task = Task::<Create>::new(
             user_id,
-            request.executor,
-            request.function_arguments,
-            request.inputs_ownership,
-            request.outputs_ownership,
+            request.executor.try_into().map_err(tonic_error)?,
+            request.function_arguments.try_into().map_err(tonic_error)?,
+            from_proto_ownership(request.inputs_ownership),
+            from_proto_ownership(request.outputs_ownership),
             function,
         )
         .map_err(|_| ManagementServiceError::InvalidTask)?;
 
         log::debug!("CreateTask: {:?}", task);
         let ts: TaskState = task.into();
-        self.write_to_db(&ts)?;
+        self.write_to_db(&ts).await?;
 
         let response = CreateTaskResponse::new(ts.external_id());
-        Ok(response)
+        Ok(Response::new(response))
     }
 
     // access control: task.participants.contains(&user_id)
-    fn get_task(
+    async fn get_task(
         &self,
         request: Request<GetTaskRequest>,
     ) -> TeaclaveServiceResponseResult<GetTaskResponse> {
         let user_id = get_request_user_id(&request)?;
-
+        let task_id = request
+            .into_inner()
+            .task_id
+            .try_into()
+            .map_err(|_| ManagementServiceError::InvalidTaskId)?;
         let ts: TaskState = self
-            .read_from_db(&request.message.task_id)
+            .read_from_db(&task_id)
+            .await
             .map_err(|_| ManagementServiceError::InvalidTaskId)?;
 
         ensure!(
@@ -605,21 +669,21 @@
         log::debug!("GetTask: {:?}", ts);
 
         let response = GetTaskResponse {
-            task_id: ts.external_id(),
-            creator: ts.creator,
-            function_id: ts.function_id,
-            function_owner: ts.function_owner,
-            function_arguments: ts.function_arguments,
-            inputs_ownership: ts.inputs_ownership,
-            outputs_ownership: ts.outputs_ownership,
-            participants: ts.participants,
-            approved_users: ts.approved_users,
-            assigned_inputs: ts.assigned_inputs.external_ids(),
-            assigned_outputs: ts.assigned_outputs.external_ids(),
-            result: ts.result,
-            status: ts.status,
+            task_id: ts.external_id().to_string(),
+            creator: ts.creator.to_string(),
+            function_id: ts.function_id.to_string(),
+            function_owner: ts.function_owner.to_string(),
+            function_arguments: ts.function_arguments.clone().into_string(),
+            inputs_ownership: to_proto_ownership(ts.inputs_ownership.clone()),
+            outputs_ownership: to_proto_ownership(ts.outputs_ownership.clone()),
+            participants: ts.participants.clone().into(),
+            approved_users: ts.approved_users.clone().into(),
+            assigned_inputs: to_proto_file_ids(ts.assigned_inputs.external_ids()),
+            assigned_outputs: to_proto_file_ids(ts.assigned_outputs.external_ids()),
+            result: Some(ts.result.into()),
+            status: i32_from_task_status(ts.status),
         };
-        Ok(response)
+        Ok(Response::new(response))
     }
 
     // access control:
@@ -632,16 +696,20 @@
     //    * inputs_ownership or outputs_ownership contains the data name
     //    * input file: OwnerList match input_file.owner
     //    * output file: OwnerList match output_file.owner
-    fn assign_data(
+    async fn assign_data(
         &self,
         request: Request<AssignDataRequest>,
     ) -> TeaclaveServiceResponseResult<AssignDataResponse> {
         let user_id = get_request_user_id(&request)?;
-
-        let request = request.message;
+        let request = request.into_inner();
+        let task_id = request
+            .task_id
+            .try_into()
+            .map_err(|_| ManagementServiceError::InvalidTaskId)?;
 
         let ts: TaskState = self
-            .read_from_db(&request.task_id)
+            .read_from_db(&task_id)
+            .await
             .map_err(|_| ManagementServiceError::InvalidTaskId)?;
 
         ensure!(
@@ -653,18 +721,20 @@
             log::warn!("Assign state error: {:?}", e);
             ManagementServiceError::TaskAssignDataError
         })?;
-
-        for (data_name, data_id) in request.inputs.iter() {
+        let inputs = from_proto_file_ids(request.inputs).map_err(tonic_error)?;
+        for (data_name, data_id) in inputs.iter() {
             let file: TeaclaveInputFile = self
                 .read_from_db(data_id)
+                .await
                 .map_err(|_| ManagementServiceError::InvalidDataId)?;
             task.assign_input(&user_id, data_name, file)
                 .map_err(|_| ManagementServiceError::PermissionDenied)?;
         }
-
-        for (data_name, data_id) in request.outputs.iter() {
+        let outputs = from_proto_file_ids(request.outputs).map_err(tonic_error)?;
+        for (data_name, data_id) in outputs.iter() {
             let file: TeaclaveOutputFile = self
                 .read_from_db(data_id)
+                .await
                 .map_err(|_| ManagementServiceError::InvalidDataId)?;
             task.assign_output(&user_id, data_name, file)
                 .map_err(|_| ManagementServiceError::PermissionDenied)?;
@@ -673,23 +743,29 @@
         log::debug!("AssignData: {:?}", task);
 
         let ts: TaskState = task.into();
-        self.write_to_db(&ts)?;
+        self.write_to_db(&ts).await?;
 
-        Ok(AssignDataResponse)
+        Ok(Response::new(AssignDataResponse {}))
     }
 
     // access_control:
     // 1) task status == Ready
     // 2) user_id in task.participants
-    fn approve_task(
+    async fn approve_task(
         &self,
         request: Request<ApproveTaskRequest>,
     ) -> TeaclaveServiceResponseResult<ApproveTaskResponse> {
         let user_id = get_request_user_id(&request)?;
 
-        let request = request.message;
+        let task_id = request
+            .into_inner()
+            .task_id
+            .try_into()
+            .map_err(|_| ManagementServiceError::InvalidTaskId)?;
+
         let ts: TaskState = self
-            .read_from_db(&request.task_id)
+            .read_from_db(&task_id)
+            .await
             .map_err(|_| ManagementServiceError::InvalidTaskId)?;
 
         let mut task: Task<Approve> = ts.try_into().map_err(|e| {
@@ -703,23 +779,28 @@
         log::debug!("ApproveTask: approve:{:?}", task);
 
         let ts: TaskState = task.into();
-        self.write_to_db(&ts)?;
+        self.write_to_db(&ts).await?;
 
-        Ok(ApproveTaskResponse)
+        Ok(Response::new(ApproveTaskResponse {}))
     }
 
     // access_control:
     // 1) task status == Approved
     // 2) user_id == task.creator
-    fn invoke_task(
+    async fn invoke_task(
         &self,
         request: Request<InvokeTaskRequest>,
     ) -> TeaclaveServiceResponseResult<InvokeTaskResponse> {
         let user_id = get_request_user_id(&request)?;
-        let request = request.message;
+        let task_id = request
+            .into_inner()
+            .task_id
+            .try_into()
+            .map_err(|_| ManagementServiceError::InvalidTaskId)?;
 
         let ts: TaskState = self
-            .read_from_db(&request.task_id)
+            .read_from_db(&task_id)
+            .await
             .map_err(|_| ManagementServiceError::InvalidTaskId)?;
 
         // Early validation
@@ -730,6 +811,7 @@
 
         let function: Function = self
             .read_from_db(&ts.function_id)
+            .await
             .map_err(|_| ManagementServiceError::InvalidFunctionId)?;
 
         log::debug!("InvokeTask: get function: {:?}", function);
@@ -741,6 +823,7 @@
         let external_id = usage.external_id();
         let mut function_usage = self
             .read_from_db::<FunctionUsage>(&external_id)
+            .await
             .map_err(|_| ManagementServiceError::InvalidFunctionId)?;
         let function_current_use_numbers = function_usage.use_numbers;
 
@@ -760,29 +843,34 @@
             .stage_for_running(&user_id, function)
             .map_err(|_| ManagementServiceError::PermissionDenied)?;
         log::debug!("InvokeTask: staged task: {:?}", staged_task);
-        self.enqueue_to_db(StagedTask::get_queue_key().as_bytes(), &staged_task)?;
+        self.enqueue_to_db(StagedTask::get_queue_key().as_bytes(), &staged_task)
+            .await?;
 
         let ts: TaskState = task.into();
-        self.write_to_db(&ts)?;
+        self.write_to_db(&ts).await?;
 
         function_usage.use_numbers = function_current_use_numbers + 1;
-        self.write_to_db(&function_usage)?;
-        Ok(InvokeTaskResponse)
+        self.write_to_db(&function_usage).await?;
+        Ok(Response::new(InvokeTaskResponse {}))
     }
 
     // access_control:
     // 1) user_id == task.creator
     // 2) user_role == admin
-    fn cancel_task(
+    async fn cancel_task(
         &self,
         request: Request<CancelTaskRequest>,
     ) -> TeaclaveServiceResponseResult<CancelTaskResponse> {
         let user_id = get_request_user_id(&request)?;
         let role = get_request_role(&request)?;
-        let request = request.message;
-
+        let task_id = request
+            .into_inner()
+            .task_id
+            .try_into()
+            .map_err(|_| ManagementServiceError::InvalidTaskId)?;
         let ts: TaskState = self
-            .read_from_db(&request.task_id)
+            .read_from_db(&task_id)
+            .await
             .map_err(|_| ManagementServiceError::InvalidTaskId)?;
 
         match role {
@@ -798,7 +886,7 @@
         match ts.status {
             // need scheduler to cancel the task
             TaskStatus::Staged | TaskStatus::Running => {
-                self.enqueue_to_db(CANCEL_QUEUE_KEY.as_bytes(), &ts)?;
+                self.enqueue_to_db(CANCEL_QUEUE_KEY.as_bytes(), &ts).await?;
             }
             _ => {
                 // early cancelation
@@ -819,40 +907,32 @@
                     ManagementServiceError::TaskCancelError("cannot update result".to_string())
                 })?;
                 let ts: TaskState = task.into();
-                self.write_to_db(&ts)?;
+                self.write_to_db(&ts).await?;
 
                 log::warn!("Canceled Task: writtenback");
             }
         }
 
-        Ok(CancelTaskResponse)
+        Ok(Response::new(CancelTaskResponse {}))
     }
 }
 
 impl TeaclaveManagementService {
-    pub(crate) fn new(storage_service_endpoint: Endpoint) -> anyhow::Result<Self> {
-        let mut i = 0;
-        let channel = loop {
-            match storage_service_endpoint.connect() {
-                Ok(channel) => break channel,
-                Err(_) => {
-                    anyhow::ensure!(i < 10, "failed to connect to storage service");
-                    log::warn!("Failed to connect to storage service, retry {}", i);
-                    i += 1;
-                }
-            }
-            std::thread::sleep(std::time::Duration::from_secs(3));
-        };
-        let storage_client = Arc::new(Mutex::new(TeaclaveStorageClient::new(channel)?));
+    pub(crate) async fn new(storage_service_endpoint: Endpoint) -> anyhow::Result<Self> {
+        let channel = storage_service_endpoint
+            .connect()
+            .await
+            .map_err(|e| anyhow!("Failed to connect to storage service, {:?}", e))?;
+        let storage_client = Arc::new(Mutex::new(TeaclaveStorageClient::new(channel)));
         let service = Self { storage_client };
 
         #[cfg(test_mode)]
-        service.add_mock_data()?;
+        service.add_mock_data().await?;
 
         Ok(service)
     }
 
-    fn write_to_db(&self, item: &impl Storable) -> Result<(), ManagementServiceError> {
+    async fn write_to_db(&self, item: &impl Storable) -> Result<(), ManagementServiceError> {
         let k = item.key();
         let v = item.to_vec()?;
         let put_request = PutRequest::new(k.as_slice(), v.as_slice());
@@ -860,13 +940,17 @@
             .storage_client
             .clone()
             .lock()
-            .map_err(|_| anyhow!("cannot lock storage client"))?
+            .await
             .put(put_request)
+            .await
             .map_err(|e| ManagementServiceError::Service(e.into()))?;
         Ok(())
     }
 
-    fn read_from_db<T: Storable>(&self, key: &ExternalID) -> Result<T, ManagementServiceError> {
+    async fn read_from_db<T: Storable>(
+        &self,
+        key: &ExternalID,
+    ) -> Result<T, ManagementServiceError> {
         ensure!(
             T::match_prefix(&key.prefix),
             anyhow!("key prefix doesn't match")
@@ -877,13 +961,15 @@
             .storage_client
             .clone()
             .lock()
-            .map_err(|_| anyhow!("cannot lock storage client"))?
+            .await
             .get(request)
-            .map_err(|e| ManagementServiceError::Service(e.into()))?;
+            .await
+            .map_err(|e| ManagementServiceError::Service(e.into()))?
+            .into_inner();
         T::from_slice(response.value.as_slice()).map_err(ManagementServiceError::Service)
     }
 
-    fn get_keys_by_prefix_from_db(
+    async fn get_keys_by_prefix_from_db(
         &self,
         prefix: impl Into<Vec<u8>>,
     ) -> Result<Vec<String>, ManagementServiceError> {
@@ -892,10 +978,12 @@
             .storage_client
             .clone()
             .lock()
-            .map_err(|_| anyhow!("cannot lock storage client"))?
+            .await
             .get_keys_by_prefix(request)
+            .await
             .map_err(|e| ManagementServiceError::Service(e.into()))?;
         Ok(response
+            .into_inner()
             .keys
             .into_iter()
             .map(String::from_utf8)
@@ -903,18 +991,19 @@
             .map_err(|_| anyhow!("cannot convert keys"))?)
     }
 
-    fn delete_from_db(&self, key: &ExternalID) -> Result<(), ManagementServiceError> {
+    async fn delete_from_db(&self, key: &ExternalID) -> Result<(), ManagementServiceError> {
         let request = DeleteRequest::new(key.to_bytes());
         self.storage_client
             .clone()
             .lock()
-            .map_err(|_| anyhow!("cannot lock storage client"))?
+            .await
             .delete(request)
+            .await
             .map_err(|e| ManagementServiceError::Service(e.into()))?;
         Ok(())
     }
 
-    fn enqueue_to_db(
+    async fn enqueue_to_db(
         &self,
         key: &[u8],
         item: &impl Storable,
@@ -925,27 +1014,28 @@
             .storage_client
             .clone()
             .lock()
-            .map_err(|_| anyhow!("cannot lock storage client"))?
+            .await
             .enqueue(enqueue_request)
+            .await
             .map_err(|e| ManagementServiceError::Service(e.into()))?;
         Ok(())
     }
 
     #[cfg(test_mode)]
-    fn add_mock_data(&self) -> anyhow::Result<()> {
+    async fn add_mock_data(&self) -> anyhow::Result<()> {
         let mut output_file = create_fusion_data(vec!["mock_user1", "frontend_user"])?;
         output_file.uuid = Uuid::parse_str("00000000-0000-0000-0000-000000000001")?;
         output_file.cmac = Some(FileAuthTag::mock());
-        self.write_to_db(&output_file)?;
+        self.write_to_db(&output_file).await?;
 
         let mut output_file = create_fusion_data(vec!["mock_user2", "mock_user3"])?;
         output_file.uuid = Uuid::parse_str("00000000-0000-0000-0000-000000000002")?;
         output_file.cmac = Some(FileAuthTag::mock());
-        self.write_to_db(&output_file)?;
+        self.write_to_db(&output_file).await?;
 
         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)?;
+        self.write_to_db(&input_file).await?;
 
         let function_input = FunctionInput::new("input", "input_desc", false);
         let function_output = FunctionOutput::new("output", "output_desc", false);
@@ -972,8 +1062,8 @@
             use_numbers: 0,
         };
 
-        self.write_to_db(&function)?;
-        self.write_to_db(&function_usage)?;
+        self.write_to_db(&function).await?;
+        self.write_to_db(&function_usage).await?;
 
         let function_output = FunctionOutput::new("output", "output_desc", false);
         let function_arg1 = FunctionArgument::new("arg1", "", true);
@@ -995,8 +1085,8 @@
             use_numbers: 0,
         };
 
-        self.write_to_db(&function)?;
-        self.write_to_db(&function_usage)?;
+        self.write_to_db(&function).await?;
+        self.write_to_db(&function_usage).await?;
 
         let function_id = Uuid::parse_str("00000000-0000-0000-0000-000000000003").unwrap();
         let function = FunctionBuilder::new()
@@ -1015,8 +1105,8 @@
             use_numbers: 0,
         };
 
-        self.write_to_db(&function)?;
-        self.write_to_db(&function_usage)?;
+        self.write_to_db(&function).await?;
+        self.write_to_db(&function_usage).await?;
 
         Ok(())
     }
@@ -1026,6 +1116,7 @@
     let user_id = request
         .metadata()
         .get("id")
+        .and_then(|x| x.to_str().ok())
         .ok_or(ManagementServiceError::MissingUserId)?;
     Ok(user_id.to_string().into())
 }
@@ -1034,6 +1125,7 @@
     let role = request
         .metadata()
         .get("role")
+        .and_then(|x| x.to_str().ok())
         .ok_or(ManagementServiceError::MissingUserRole)?;
     Ok(UserRole::from_str(role))
 }
diff --git a/services/proto/Cargo.toml b/services/proto/Cargo.toml
index acddc89..43693f7 100644
--- a/services/proto/Cargo.toml
+++ b/services/proto/Cargo.toml
@@ -27,28 +27,22 @@
 default = []
 app = [
     "teaclave_types/app",
-    "teaclave_rpc/app",
     "teaclave_crypto/app",
 ]
 mesalock_sgx = [
     "teaclave_types/mesalock_sgx",
-    "teaclave_rpc/mesalock_sgx",
     "teaclave_crypto/mesalock_sgx",
 ]
 cov = ["sgx_cov"]
 
 [dependencies]
 anyhow       = { version = "1.0.26" }
-base64       = { version = "0.13.0" }
-cfg-if       = { version = "0.1.9" }
-prost        = { version = "0.11" }
-rand         = { version = "0.8.5" }
+prost        = { version = "0.9" }
 serde        = { version = "1.0.39", features = ["derive"] }
 serde_json   = { version = "1.0.39" }
+tonic        = { version = "0.6.1", features = ["tls", "compression"]}
 url          = { version = "2.1.1" }
 uuid          = { version = "0.8.1", features = ["v4"] }
-
-teaclave_rpc = { path = "../../rpc" }
 teaclave_types = { path = "../../types" }
 teaclave_crypto = { path = "../../crypto" }
 
@@ -56,3 +50,6 @@
 
 [target.'cfg(not(target_vendor = "teaclave"))'.dependencies]
 sgx_types    = { version = "2.0.0" }
+
+[build-dependencies]
+tonic-build = { version = "0.6.0", features = ["prost","compression"] }
\ No newline at end of file
diff --git a/services/proto/build.rs b/services/proto/build.rs
index 78bf810..af8dc59 100644
--- a/services/proto/build.rs
+++ b/services/proto/build.rs
@@ -16,10 +16,6 @@
 // under the License.
 
 use std::env;
-use std::path::Path;
-use std::path::PathBuf;
-use std::process::Command;
-use std::str;
 
 fn main() {
     let proto_files = [
@@ -34,54 +30,16 @@
 
     let out_dir = env::var("OUT_DIR").expect("$OUT_DIR not set. Please build with cargo");
     println!("cargo:rerun-if-changed=build.rs");
-    println!("cargo:rerun-if-changed=proto_gen/templates/proto.j2");
-    println!("cargo:rerun-if-changed=proto_gen/main.rs");
 
     for pf in proto_files.iter() {
         println!("cargo:rerun-if-changed={}", pf);
     }
 
-    let target_dir = match env::var("TEACLAVE_SYMLINKS") {
-        Ok(teaclave_symlinks) => {
-            Path::new(&teaclave_symlinks).join("teaclave_build/target/proto_gen")
-        }
-        Err(_) => env::current_dir().unwrap().join("target/proto_gen"),
-    };
-    let current_dir: PathBuf = match env::var("MT_SGXAPP_TOML_DIR") {
-        Ok(sgxapp_toml_dir) => Path::new(&sgxapp_toml_dir).into(),
-        // This fallback is only for compiling rust client sdk with cargo
-        Err(_) => Path::new("../../").into(),
-    };
-
-    let proto_files = [
-        "services/proto/src/proto/teaclave_access_control_service.proto",
-        "services/proto/src/proto/teaclave_authentication_service.proto",
-        "services/proto/src/proto/teaclave_common.proto",
-        "services/proto/src/proto/teaclave_storage_service.proto",
-        "services/proto/src/proto/teaclave_frontend_service.proto",
-        "services/proto/src/proto/teaclave_management_service.proto",
-        "services/proto/src/proto/teaclave_scheduler_service.proto",
-    ];
-    let mut c = Command::new("cargo");
-    // Use CARGO_ENCODED_RUSTFLAGS to override RUSTFLAGS which makes the run fail.
-    c.current_dir(&current_dir)
-        .env("CARGO_ENCODED_RUSTFLAGS", "");
-    c.args([
-        "run",
-        "--target-dir",
-        &target_dir.to_string_lossy(),
-        "--manifest-path",
-        "services/proto/proto_gen/Cargo.toml",
-    ]);
-
-    c.args(["--", "-i", "services/proto/src/proto", "-d", &out_dir, "-p"])
-        .args(proto_files);
-    let output = c.output().expect("Generate proto failed");
-    if !output.status.success() {
-        panic!(
-            "stdout: {:?}, stderr: {:?}",
-            str::from_utf8(&output.stderr).unwrap(),
-            str::from_utf8(&output.stderr).unwrap()
-        );
+    if let Err(e) = tonic_build::configure()
+        .out_dir(out_dir)
+        .type_attribute(".", "#[derive(serde::Serialize, serde::Deserialize)]")
+        .compile(&proto_files, &["src/proto"])
+    {
+        panic!("proto build error: {:?}", e);
     }
 }
diff --git a/services/proto/proto_gen/Cargo.lock b/services/proto/proto_gen/Cargo.lock
deleted file mode 100644
index bb27d7d..0000000
--- a/services/proto/proto_gen/Cargo.lock
+++ /dev/null
@@ -1,755 +0,0 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-version = 3
-
-[[package]]
-name = "ansi_term"
-version = "0.12.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
-dependencies = [
- "winapi",
-]
-
-[[package]]
-name = "anyhow"
-version = "1.0.70"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4"
-
-[[package]]
-name = "askama"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3dc2a4b6d7f812d2b13d251ae792caecebd635d6401761162d4b71d5ebe1a010"
-dependencies = [
- "askama_derive",
- "askama_escape",
- "askama_shared",
-]
-
-[[package]]
-name = "askama_derive"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23ee2fff0f22ad5d215cace1227cd036c28e81e26206763bb837b6d0e766c87d"
-dependencies = [
- "askama_shared",
- "nom",
- "proc-macro2 0.4.30",
- "quote 0.6.13",
- "syn 0.15.44",
-]
-
-[[package]]
-name = "askama_escape"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b0de942230b5beedaa9e1d64df5b76fa1c97002e4c7982897be899cccf40621d"
-
-[[package]]
-name = "askama_shared"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a6dfa6b6d254fd066a8bbed9a8f913123e3f701db89216ad4f0aff04ad87718c"
-dependencies = [
- "askama_escape",
- "humansize",
- "num-traits",
- "serde",
- "serde_derive",
- "toml",
-]
-
-[[package]]
-name = "atty"
-version = "0.2.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
-dependencies = [
- "hermit-abi 0.1.19",
- "libc",
- "winapi",
-]
-
-[[package]]
-name = "autocfg"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
-
-[[package]]
-name = "bitflags"
-version = "1.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
-
-[[package]]
-name = "bytes"
-version = "1.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
-
-[[package]]
-name = "cc"
-version = "1.0.79"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
-
-[[package]]
-name = "cfg-if"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
-
-[[package]]
-name = "clap"
-version = "2.34.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
-dependencies = [
- "ansi_term",
- "atty",
- "bitflags",
- "strsim",
- "textwrap",
- "unicode-width",
- "vec_map",
-]
-
-[[package]]
-name = "either"
-version = "1.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
-
-[[package]]
-name = "errno"
-version = "0.2.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1"
-dependencies = [
- "errno-dragonfly",
- "libc",
- "winapi",
-]
-
-[[package]]
-name = "errno-dragonfly"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
-dependencies = [
- "cc",
- "libc",
-]
-
-[[package]]
-name = "fastrand"
-version = "1.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be"
-dependencies = [
- "instant",
-]
-
-[[package]]
-name = "fixedbitset"
-version = "0.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
-
-[[package]]
-name = "hashbrown"
-version = "0.12.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
-
-[[package]]
-name = "heck"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
-dependencies = [
- "unicode-segmentation",
-]
-
-[[package]]
-name = "heck"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
-
-[[package]]
-name = "hermit-abi"
-version = "0.1.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "hermit-abi"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
-
-[[package]]
-name = "humansize"
-version = "1.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02296996cb8796d7c6e3bc2d9211b7802812d36999a51bb754123ead7d37d026"
-
-[[package]]
-name = "indexmap"
-version = "1.9.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
-dependencies = [
- "autocfg",
- "hashbrown",
-]
-
-[[package]]
-name = "instant"
-version = "0.1.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
-dependencies = [
- "cfg-if",
-]
-
-[[package]]
-name = "io-lifetimes"
-version = "1.0.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09270fd4fa1111bc614ed2246c7ef56239a3063d5be0d1ec3b589c505d400aeb"
-dependencies = [
- "hermit-abi 0.3.1",
- "libc",
- "windows-sys 0.45.0",
-]
-
-[[package]]
-name = "itertools"
-version = "0.10.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
-dependencies = [
- "either",
-]
-
-[[package]]
-name = "lazy_static"
-version = "1.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
-
-[[package]]
-name = "libc"
-version = "0.2.140"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
-
-[[package]]
-name = "linux-raw-sys"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
-
-[[package]]
-name = "log"
-version = "0.4.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
-dependencies = [
- "cfg-if",
-]
-
-[[package]]
-name = "memchr"
-version = "2.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
-
-[[package]]
-name = "multimap"
-version = "0.8.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a"
-
-[[package]]
-name = "nom"
-version = "4.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6"
-dependencies = [
- "memchr",
- "version_check 0.1.5",
-]
-
-[[package]]
-name = "num-traits"
-version = "0.2.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
-dependencies = [
- "autocfg",
-]
-
-[[package]]
-name = "once_cell"
-version = "1.17.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
-
-[[package]]
-name = "petgraph"
-version = "0.6.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4"
-dependencies = [
- "fixedbitset",
- "indexmap",
-]
-
-[[package]]
-name = "prettyplease"
-version = "0.1.25"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86"
-dependencies = [
- "proc-macro2 1.0.54",
- "syn 1.0.109",
-]
-
-[[package]]
-name = "proc-macro-error"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
-dependencies = [
- "proc-macro-error-attr",
- "proc-macro2 1.0.54",
- "quote 1.0.26",
- "syn 1.0.109",
- "version_check 0.9.4",
-]
-
-[[package]]
-name = "proc-macro-error-attr"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
-dependencies = [
- "proc-macro2 1.0.54",
- "quote 1.0.26",
- "version_check 0.9.4",
-]
-
-[[package]]
-name = "proc-macro2"
-version = "0.4.30"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
-dependencies = [
- "unicode-xid",
-]
-
-[[package]]
-name = "proc-macro2"
-version = "1.0.54"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e472a104799c74b514a57226160104aa483546de37e839ec50e3c2e41dd87534"
-dependencies = [
- "unicode-ident",
-]
-
-[[package]]
-name = "prost"
-version = "0.11.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e48e50df39172a3e7eb17e14642445da64996989bc212b583015435d39a58537"
-dependencies = [
- "bytes",
- "prost-derive",
-]
-
-[[package]]
-name = "prost-build"
-version = "0.11.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2c828f93f5ca4826f97fedcbd3f9a536c16b12cff3dbbb4a007f932bbad95b12"
-dependencies = [
- "bytes",
- "heck 0.4.1",
- "itertools",
- "lazy_static",
- "log",
- "multimap",
- "petgraph",
- "prettyplease",
- "prost",
- "prost-types",
- "regex",
- "syn 1.0.109",
- "tempfile",
- "which",
-]
-
-[[package]]
-name = "prost-derive"
-version = "0.11.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ea9b0f8cbe5e15a8a042d030bd96668db28ecb567ec37d691971ff5731d2b1b"
-dependencies = [
- "anyhow",
- "itertools",
- "proc-macro2 1.0.54",
- "quote 1.0.26",
- "syn 1.0.109",
-]
-
-[[package]]
-name = "prost-types"
-version = "0.11.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "379119666929a1afd7a043aa6cf96fa67a6dce9af60c88095a4686dbce4c9c88"
-dependencies = [
- "prost",
-]
-
-[[package]]
-name = "quote"
-version = "0.6.13"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
-dependencies = [
- "proc-macro2 0.4.30",
-]
-
-[[package]]
-name = "quote"
-version = "1.0.26"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
-dependencies = [
- "proc-macro2 1.0.54",
-]
-
-[[package]]
-name = "redox_syscall"
-version = "0.2.16"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
-dependencies = [
- "bitflags",
-]
-
-[[package]]
-name = "regex"
-version = "1.7.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d"
-dependencies = [
- "regex-syntax",
-]
-
-[[package]]
-name = "regex-syntax"
-version = "0.6.29"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
-
-[[package]]
-name = "rustix"
-version = "0.36.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "db4165c9963ab29e422d6c26fbc1d37f15bace6b2810221f9d925023480fcf0e"
-dependencies = [
- "bitflags",
- "errno",
- "io-lifetimes",
- "libc",
- "linux-raw-sys",
- "windows-sys 0.45.0",
-]
-
-[[package]]
-name = "serde"
-version = "1.0.159"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c04e8343c3daeec41f58990b9d77068df31209f2af111e059e9fe9646693065"
-
-[[package]]
-name = "serde_derive"
-version = "1.0.159"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c614d17805b093df4b147b51339e7e44bf05ef59fba1e45d83500bcfb4d8585"
-dependencies = [
- "proc-macro2 1.0.54",
- "quote 1.0.26",
- "syn 2.0.11",
-]
-
-[[package]]
-name = "strsim"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
-
-[[package]]
-name = "structopt"
-version = "0.3.26"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10"
-dependencies = [
- "clap",
- "lazy_static",
- "structopt-derive",
-]
-
-[[package]]
-name = "structopt-derive"
-version = "0.4.18"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0"
-dependencies = [
- "heck 0.3.3",
- "proc-macro-error",
- "proc-macro2 1.0.54",
- "quote 1.0.26",
- "syn 1.0.109",
-]
-
-[[package]]
-name = "syn"
-version = "0.15.44"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5"
-dependencies = [
- "proc-macro2 0.4.30",
- "quote 0.6.13",
- "unicode-xid",
-]
-
-[[package]]
-name = "syn"
-version = "1.0.109"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
-dependencies = [
- "proc-macro2 1.0.54",
- "quote 1.0.26",
- "unicode-ident",
-]
-
-[[package]]
-name = "syn"
-version = "2.0.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "21e3787bb71465627110e7d87ed4faaa36c1f61042ee67badb9e2ef173accc40"
-dependencies = [
- "proc-macro2 1.0.54",
- "quote 1.0.26",
- "unicode-ident",
-]
-
-[[package]]
-name = "teaclave_proto_gen"
-version = "0.5.1"
-dependencies = [
- "askama",
- "prost",
- "prost-build",
- "prost-types",
- "structopt",
-]
-
-[[package]]
-name = "tempfile"
-version = "3.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af18f7ae1acd354b992402e9ec5864359d693cd8a79dcbef59f76891701c1e95"
-dependencies = [
- "cfg-if",
- "fastrand",
- "redox_syscall",
- "rustix",
- "windows-sys 0.42.0",
-]
-
-[[package]]
-name = "textwrap"
-version = "0.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
-dependencies = [
- "unicode-width",
-]
-
-[[package]]
-name = "toml"
-version = "0.4.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f"
-dependencies = [
- "serde",
-]
-
-[[package]]
-name = "unicode-ident"
-version = "1.0.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
-
-[[package]]
-name = "unicode-segmentation"
-version = "1.10.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36"
-
-[[package]]
-name = "unicode-width"
-version = "0.1.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
-
-[[package]]
-name = "unicode-xid"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
-
-[[package]]
-name = "vec_map"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
-
-[[package]]
-name = "version_check"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
-
-[[package]]
-name = "version_check"
-version = "0.9.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
-
-[[package]]
-name = "which"
-version = "4.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269"
-dependencies = [
- "either",
- "libc",
- "once_cell",
-]
-
-[[package]]
-name = "winapi"
-version = "0.3.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
-dependencies = [
- "winapi-i686-pc-windows-gnu",
- "winapi-x86_64-pc-windows-gnu",
-]
-
-[[package]]
-name = "winapi-i686-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
-
-[[package]]
-name = "winapi-x86_64-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
-
-[[package]]
-name = "windows-sys"
-version = "0.42.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
-dependencies = [
- "windows_aarch64_gnullvm",
- "windows_aarch64_msvc",
- "windows_i686_gnu",
- "windows_i686_msvc",
- "windows_x86_64_gnu",
- "windows_x86_64_gnullvm",
- "windows_x86_64_msvc",
-]
-
-[[package]]
-name = "windows-sys"
-version = "0.45.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
-dependencies = [
- "windows-targets",
-]
-
-[[package]]
-name = "windows-targets"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
-dependencies = [
- "windows_aarch64_gnullvm",
- "windows_aarch64_msvc",
- "windows_i686_gnu",
- "windows_i686_msvc",
- "windows_x86_64_gnu",
- "windows_x86_64_gnullvm",
- "windows_x86_64_msvc",
-]
-
-[[package]]
-name = "windows_aarch64_gnullvm"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
-
-[[package]]
-name = "windows_aarch64_msvc"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
-
-[[package]]
-name = "windows_i686_gnu"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
-
-[[package]]
-name = "windows_i686_msvc"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
-
-[[package]]
-name = "windows_x86_64_gnu"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
-
-[[package]]
-name = "windows_x86_64_gnullvm"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
-
-[[package]]
-name = "windows_x86_64_msvc"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
diff --git a/services/proto/proto_gen/Cargo.toml b/services/proto/proto_gen/Cargo.toml
deleted file mode 100644
index 0e725b5..0000000
--- a/services/proto/proto_gen/Cargo.toml
+++ /dev/null
@@ -1,37 +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.
-
-[package]
-name = "teaclave_proto_gen"
-version = "0.5.1"
-authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
-description = "Generating Rust protocols from protobuf."
-license = "Apache-2.0"
-edition = "2021"
-
-[[bin]]
-name = "proto_gen"
-path = "main.rs"
-
-[dependencies]
-structopt   = { version = "0.3" }
-prost-build = { version = "0.11" }
-prost       = { version = "0.11" }
-prost-types = { version = "0.11" }
-askama      = { version = "0.8" }
-
-[workspace]
diff --git a/services/proto/proto_gen/main.rs b/services/proto/proto_gen/main.rs
deleted file mode 100644
index d078e60..0000000
--- a/services/proto/proto_gen/main.rs
+++ /dev/null
@@ -1,121 +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 askama::Template;
-use std::path;
-use structopt::StructOpt;
-
-#[derive(Debug)]
-pub struct MesaTEEServiceGenerator;
-
-#[derive(Template)]
-#[template(path = "proto.j2")]
-struct ProtoTemplate {
-    service: Service,
-}
-
-struct Method {
-    name: String,
-    proto_name: String,
-    input_type: String,
-    impl_input_type: String,
-    output_type: String,
-    impl_output_type: String,
-}
-
-struct Service {
-    proto_name: String,
-    methods: Vec<Method>,
-}
-
-impl Service {
-    fn from_prost(prost_service: &prost_build::Service) -> Self {
-        fn convert_to_impl_type(current_package_name: &str, proto_type: &str) -> String {
-            format!(
-                "crate::{}::{}",
-                current_package_name,
-                proto_type.rsplitn(2, "::").collect::<Vec<&str>>()[0].replacen("_proto", "", 1)
-            )
-        }
-        let mut methods = vec![];
-        let package_name = prost_service.package.trim_end_matches("_proto");
-        for m in prost_service.methods.iter() {
-            let impl_input_type = convert_to_impl_type(package_name, &m.input_type);
-            let impl_output_type = convert_to_impl_type(package_name, &m.output_type);
-
-            let method = Method {
-                name: m.name.clone(),
-                proto_name: m.proto_name.clone(),
-                input_type: m.input_type.clone(),
-                impl_input_type,
-                output_type: m.output_type.clone(),
-                impl_output_type,
-            };
-            methods.push(method);
-        }
-        Self {
-            proto_name: prost_service.proto_name.clone(),
-            methods,
-        }
-    }
-}
-
-impl MesaTEEServiceGenerator {
-    fn generate_from_template(&mut self, service: &prost_build::Service, buf: &mut String) {
-        let service = Service::from_prost(service);
-        let proto_template = ProtoTemplate { service };
-        buf.push_str(&proto_template.render().unwrap());
-    }
-}
-
-impl prost_build::ServiceGenerator for MesaTEEServiceGenerator {
-    fn generate(&mut self, service: prost_build::Service, buf: &mut String) {
-        self.generate_from_template(&service, buf);
-    }
-}
-
-pub fn get_default_config() -> prost_build::Config {
-    let mut config = prost_build::Config::new();
-    config.service_generator(Box::new(MesaTEEServiceGenerator));
-    config.type_attribute(".", "#[derive(serde::Serialize, serde::Deserialize)]");
-    config
-}
-
-#[derive(Debug, StructOpt)]
-struct Cli {
-    #[structopt(short = "p", required = true)]
-    /// Paths to .proto files to compile. Any transitively imported .proto files
-    /// are automatically be included.
-    protos: Vec<path::PathBuf>,
-
-    #[structopt(short = "i", required = true)]
-    /// Paths to directories in which to search for imports. Directories are
-    /// searched in order. The .proto files passed in protos must be found in
-    /// one of the provided include directories.
-    includes: Vec<path::PathBuf>,
-
-    #[structopt(short = "d", required = true)]
-    /// Configures the output directory where generated Rust files will be written.
-    out_dir: path::PathBuf,
-}
-
-fn main() {
-    let args = Cli::from_args();
-    let mut config = get_default_config();
-    config.out_dir(args.out_dir);
-    config.compile_protos(&args.protos, &args.includes).unwrap();
-}
diff --git a/services/proto/proto_gen/templates/proto.j2 b/services/proto/proto_gen/templates/proto.j2
deleted file mode 100644
index 84ffdaa..0000000
--- a/services/proto/proto_gen/templates/proto.j2
+++ /dev/null
@@ -1,129 +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.
-#}
-
-#[derive(Clone, serde::Serialize, serde::Deserialize, Debug)]
-#[serde(rename_all = "snake_case")]
-pub enum {{ service.proto_name }}Request {
-    {%- for m in service.methods %}
-    {{ m.proto_name }}({{ m.input_type }}),
-    {%- endfor %}
-}
-
-#[allow(clippy::large_enum_variant)]
-#[derive(Clone, serde::Serialize, serde::Deserialize, Debug)]
-#[serde(tag = "response", content = "content", rename_all = "snake_case")]
-pub enum {{ service.proto_name }}Response {
-    {%- for m in service.methods %}
-    {{ m.proto_name }}({{ m.output_type }}),
-    {%- endfor %}
-}
-
-pub trait {{ service.proto_name }} {
-    {%- for m in service.methods %}
-      fn {{ m.name }}(
-          &self,
-          request: teaclave_rpc::Request<{{ m.impl_input_type }}>
-      ) -> teaclave_types::TeaclaveServiceResponseResult<{{ m.impl_output_type }}>;
-    {%- endfor %}
-
-    fn dispatch(
-      &self,
-      request: teaclave_rpc::Request<{{ service.proto_name }}Request>
-    ) -> teaclave_types::TeaclaveServiceResponseResult<{{ service.proto_name }}Response> {
-         use core::convert::TryFrom;
-         use std::string::ToString;
-         match request.message {
-             {%- for m in service.methods %}
-             {{ service.proto_name }}Request::{{ m.proto_name }}(r) => {
-                 let r = {{ m.impl_input_type }}::try_from(r)
-                     .map_err(|_| teaclave_types::TeaclaveServiceResponseError::InternalError("internal".to_string()))?;
-                 let r = teaclave_rpc::Request {
-                     metadata: request.metadata,
-                     message: r,
-                 };
-                 let response = self.{{ m.name }}(r)?;
-                 let response = {{ m.output_type }}::from(response);
-                 Ok(response).map({{ service.proto_name }}Response::{{ m.proto_name }})
-             },
-             {%- endfor %}
-         }
-    }
-}
-
-pub struct {{ service.proto_name }}Client {
-    channel: teaclave_rpc::channel::SgxTrustedTlsChannel<{{ service.proto_name }}Request, {{ service.proto_name }}Response>,
-    metadata: std::collections::HashMap<std::string::String, std::string::String>,
-}
-
-impl {{ service.proto_name }}Client {
-    pub fn new(
-        channel: teaclave_rpc::channel::SgxTrustedTlsChannel<
-            {{ service.proto_name }}Request,
-            {{ service.proto_name }}Response
-        >
-    ) -> anyhow::Result<Self> {
-        let metadata = std::collections::HashMap::new();
-        Ok(Self { channel, metadata })
-    }
-
-    pub fn new_with_metadata(
-        channel: teaclave_rpc::channel::SgxTrustedTlsChannel<
-            {{ service.proto_name }}Request,
-            {{ service.proto_name }}Response
-        >,
-        metadata: std::collections::HashMap<std::string::String, std::string::String>,
-    ) -> anyhow::Result<Self> {
-        Ok(Self { channel, metadata })
-    }
-
-    {%- for m in service.methods %}
-    pub fn {{ m.name }}<T: teaclave_rpc::IntoRequest<{{ service.proto_name }}Request>>(
-        &mut self,
-        request: T
-    ) -> teaclave_types::TeaclaveServiceResponseResult<{{ m.impl_output_type }}> {
-        use core::convert::TryInto;
-        use std::string::ToString;
-        {# {%- if service.methods.len() > 1 %} #}
-        {# use std::string::ToString; #}
-        {# {%- endif %} #}
-        let mut request = request.into_request();
-        request.metadata = self.metadata.clone();
-
-        match self.channel.invoke(request) {
-            Ok({{ service.proto_name }}Response::{{ m.proto_name }}(response)) => Ok(response.try_into().map_err(|_| teaclave_types::TeaclaveServiceResponseError::InternalError("internal".to_string()))?),
-            Err(e) => Err(e),
-            {%- if service.methods.len() > 1 %}
-            _ => Err(teaclave_types::TeaclaveServiceResponseError::InternalError("internal".to_string())),
-            {%- endif %}
-        }
-    }
-    {%- endfor %}
-
-    pub fn metadata(&self) -> &std::collections::HashMap<std::string::String, std::string::String> {
-        &self.metadata
-    }
-
-    pub fn metadata_mut(&mut self) -> &mut std::collections::HashMap<std::string::String, std::string::String> {
-        &mut self.metadata
-    }
-
-    pub fn set_metadata(&mut self, metadata: std::collections::HashMap<std::string::String, std::string::String>) {
-        self.metadata = metadata
-    }
-}
diff --git a/services/proto/src/teaclave_access_control_service.rs b/services/proto/src/teaclave_access_control_service.rs
index 67deebb..ca7d159 100644
--- a/services/proto/src/teaclave_access_control_service.rs
+++ b/services/proto/src/teaclave_access_control_service.rs
@@ -16,20 +16,11 @@
 // under the License.
 
 use crate::teaclave_access_control_service_proto as proto;
-use anyhow::{Error, Result};
-use teaclave_rpc::into_request;
-
-pub use proto::TeaclaveAccessControl;
-pub use proto::TeaclaveAccessControlClient;
-pub use proto::TeaclaveAccessControlRequest;
-pub use proto::TeaclaveAccessControlResponse;
-
-#[into_request(TeaclaveAccessControlRequest::AuthorizeData)]
-#[derive(Debug)]
-pub struct AuthorizeDataRequest {
-    pub subject_user_id: String,
-    pub object_data_id: String,
-}
+pub use proto::teaclave_access_control_client::TeaclaveAccessControlClient;
+pub use proto::teaclave_access_control_server::{
+    TeaclaveAccessControl, TeaclaveAccessControlServer,
+};
+pub use proto::*;
 
 impl AuthorizeDataRequest {
     pub fn new(subject_user_id: impl Into<String>, object_data_id: impl Into<String>) -> Self {
@@ -40,25 +31,12 @@
     }
 }
 
-#[into_request(TeaclaveAccessControlResponse::AuthorizeData)]
-#[derive(Debug)]
-pub struct AuthorizeDataResponse {
-    pub accept: bool,
-}
-
 impl AuthorizeDataResponse {
     pub fn new(accept: bool) -> Self {
         Self { accept }
     }
 }
 
-#[into_request(TeaclaveAccessControlRequest::AuthorizeFunction)]
-#[derive(Debug)]
-pub struct AuthorizeFunctionRequest {
-    pub subject_user_id: String,
-    pub object_function_id: String,
-}
-
 impl AuthorizeFunctionRequest {
     pub fn new(subject_user_id: impl Into<String>, object_function_id: impl Into<String>) -> Self {
         Self {
@@ -68,25 +46,12 @@
     }
 }
 
-#[into_request(TeaclaveAccessControlResponse::AuthorizeFunction)]
-#[derive(Debug)]
-pub struct AuthorizeFunctionResponse {
-    pub accept: bool,
-}
-
 impl AuthorizeFunctionResponse {
     pub fn new(accept: bool) -> Self {
         Self { accept }
     }
 }
 
-#[into_request(TeaclaveAccessControlRequest::AuthorizeTask)]
-#[derive(Debug)]
-pub struct AuthorizeTaskRequest {
-    pub subject_user_id: String,
-    pub object_task_id: String,
-}
-
 impl AuthorizeTaskRequest {
     pub fn new(subject_user_id: impl Into<String>, object_task_id: impl Into<String>) -> Self {
         Self {
@@ -96,199 +61,14 @@
     }
 }
 
-#[into_request(TeaclaveAccessControlResponse::AuthorizeTask)]
-#[derive(Debug)]
-pub struct AuthorizeTaskResponse {
-    pub accept: bool,
-}
-
 impl AuthorizeTaskResponse {
     pub fn new(accept: bool) -> Self {
         Self { accept }
     }
 }
 
-#[into_request(TeaclaveAccessControlRequest::AuthorizeStagedTask)]
-#[derive(Debug)]
-pub struct AuthorizeStagedTaskRequest {
-    pub subject_task_id: String,
-    pub object_function_id: String,
-    pub object_input_data_id_list: Vec<String>,
-    pub object_output_data_id_list: Vec<String>,
-}
-
-#[into_request(TeaclaveAccessControlResponse::AuthorizeStagedTask)]
-#[derive(Debug)]
-pub struct AuthorizeStagedTaskResponse {
-    pub accept: bool,
-}
-
 impl AuthorizeStagedTaskResponse {
     pub fn new(accept: bool) -> Self {
         Self { accept }
     }
 }
-
-impl std::convert::TryFrom<proto::AuthorizeDataRequest> for AuthorizeDataRequest {
-    type Error = Error;
-
-    fn try_from(proto: proto::AuthorizeDataRequest) -> Result<Self> {
-        let ret = Self {
-            subject_user_id: proto.subject_user_id,
-            object_data_id: proto.object_data_id,
-        };
-
-        Ok(ret)
-    }
-}
-
-impl From<AuthorizeDataRequest> for proto::AuthorizeDataRequest {
-    fn from(request: AuthorizeDataRequest) -> Self {
-        Self {
-            subject_user_id: request.subject_user_id,
-            object_data_id: request.object_data_id,
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::AuthorizeDataResponse> for AuthorizeDataResponse {
-    type Error = Error;
-
-    fn try_from(proto: proto::AuthorizeDataResponse) -> Result<Self> {
-        Ok(Self {
-            accept: proto.accept,
-        })
-    }
-}
-
-impl From<AuthorizeDataResponse> for proto::AuthorizeDataResponse {
-    fn from(response: AuthorizeDataResponse) -> Self {
-        Self {
-            accept: response.accept,
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::AuthorizeFunctionRequest> for AuthorizeFunctionRequest {
-    type Error = Error;
-
-    fn try_from(proto: proto::AuthorizeFunctionRequest) -> Result<Self> {
-        let ret = Self {
-            subject_user_id: proto.subject_user_id,
-            object_function_id: proto.object_function_id,
-        };
-
-        Ok(ret)
-    }
-}
-
-impl From<AuthorizeFunctionRequest> for proto::AuthorizeFunctionRequest {
-    fn from(request: AuthorizeFunctionRequest) -> Self {
-        Self {
-            subject_user_id: request.subject_user_id,
-            object_function_id: request.object_function_id,
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::AuthorizeFunctionResponse> for AuthorizeFunctionResponse {
-    type Error = Error;
-
-    fn try_from(proto: proto::AuthorizeFunctionResponse) -> Result<Self> {
-        Ok(Self {
-            accept: proto.accept,
-        })
-    }
-}
-
-impl From<AuthorizeFunctionResponse> for proto::AuthorizeFunctionResponse {
-    fn from(response: AuthorizeFunctionResponse) -> Self {
-        Self {
-            accept: response.accept,
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::AuthorizeTaskRequest> for AuthorizeTaskRequest {
-    type Error = Error;
-
-    fn try_from(proto: proto::AuthorizeTaskRequest) -> Result<Self> {
-        let ret = Self {
-            subject_user_id: proto.subject_user_id,
-            object_task_id: proto.object_task_id,
-        };
-
-        Ok(ret)
-    }
-}
-
-impl From<AuthorizeTaskRequest> for proto::AuthorizeTaskRequest {
-    fn from(request: AuthorizeTaskRequest) -> Self {
-        Self {
-            subject_user_id: request.subject_user_id,
-            object_task_id: request.object_task_id,
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::AuthorizeTaskResponse> for AuthorizeTaskResponse {
-    type Error = Error;
-
-    fn try_from(proto: proto::AuthorizeTaskResponse) -> Result<Self> {
-        Ok(Self {
-            accept: proto.accept,
-        })
-    }
-}
-
-impl From<AuthorizeTaskResponse> for proto::AuthorizeTaskResponse {
-    fn from(response: AuthorizeTaskResponse) -> Self {
-        Self {
-            accept: response.accept,
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::AuthorizeStagedTaskRequest> for AuthorizeStagedTaskRequest {
-    type Error = Error;
-
-    fn try_from(proto: proto::AuthorizeStagedTaskRequest) -> Result<Self> {
-        let ret = Self {
-            subject_task_id: proto.subject_task_id,
-            object_function_id: proto.object_function_id,
-            object_input_data_id_list: proto.object_input_data_id_list,
-            object_output_data_id_list: proto.object_output_data_id_list,
-        };
-
-        Ok(ret)
-    }
-}
-
-impl From<AuthorizeStagedTaskRequest> for proto::AuthorizeStagedTaskRequest {
-    fn from(request: AuthorizeStagedTaskRequest) -> Self {
-        Self {
-            subject_task_id: request.subject_task_id,
-            object_function_id: request.object_function_id,
-            object_input_data_id_list: request.object_input_data_id_list,
-            object_output_data_id_list: request.object_output_data_id_list,
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::AuthorizeStagedTaskResponse> for AuthorizeStagedTaskResponse {
-    type Error = Error;
-
-    fn try_from(proto: proto::AuthorizeStagedTaskResponse) -> Result<Self> {
-        Ok(Self {
-            accept: proto.accept,
-        })
-    }
-}
-
-impl From<AuthorizeStagedTaskResponse> for proto::AuthorizeStagedTaskResponse {
-    fn from(response: AuthorizeStagedTaskResponse) -> Self {
-        Self {
-            accept: response.accept,
-        }
-    }
-}
diff --git a/services/proto/src/teaclave_authentication_service.rs b/services/proto/src/teaclave_authentication_service.rs
index 85d0808..d0357b7 100644
--- a/services/proto/src/teaclave_authentication_service.rs
+++ b/services/proto/src/teaclave_authentication_service.rs
@@ -15,33 +15,20 @@
 // specific language governing permissions and limitations
 // under the License.
 
-use anyhow::anyhow;
 use anyhow::{Error, Result};
-use core::convert::TryInto;
-use teaclave_rpc::into_request;
 
 use crate::teaclave_authentication_service_proto as proto;
 use crate::teaclave_common;
+pub use proto::teaclave_authentication_api_client::TeaclaveAuthenticationApiClient;
+pub use proto::teaclave_authentication_api_server::TeaclaveAuthenticationApi;
+pub use proto::teaclave_authentication_api_server::TeaclaveAuthenticationApiServer;
+pub use proto::teaclave_authentication_internal_client::TeaclaveAuthenticationInternalClient;
+pub use proto::teaclave_authentication_internal_server::{
+    TeaclaveAuthenticationInternal, TeaclaveAuthenticationInternalServer,
+};
+pub use proto::*;
 use teaclave_types::UserAuthClaims;
 
-pub use proto::TeaclaveAuthenticationApi;
-pub use proto::TeaclaveAuthenticationApiClient;
-pub use proto::TeaclaveAuthenticationApiRequest;
-pub use proto::TeaclaveAuthenticationApiResponse;
-pub use proto::TeaclaveAuthenticationInternal;
-pub use proto::TeaclaveAuthenticationInternalClient;
-pub use proto::TeaclaveAuthenticationInternalRequest;
-pub use proto::TeaclaveAuthenticationInternalResponse;
-
-#[into_request(TeaclaveAuthenticationApiRequest::UserRegister)]
-#[derive(Debug)]
-pub struct UserRegisterRequest {
-    pub id: std::string::String,
-    pub password: std::string::String,
-    pub role: std::string::String,
-    pub attribute: std::string::String,
-}
-
 impl UserRegisterRequest {
     pub fn new(
         id: impl Into<String>,
@@ -58,19 +45,6 @@
     }
 }
 
-#[into_request(TeaclaveAuthenticationApiResponse::UserRegister)]
-#[derive(Debug, Default)]
-pub struct UserRegisterResponse;
-
-#[into_request(TeaclaveAuthenticationApiRequest::UserUpdate)]
-#[derive(Debug)]
-pub struct UserUpdateRequest {
-    pub id: std::string::String,
-    pub password: std::string::String,
-    pub role: std::string::String,
-    pub attribute: std::string::String,
-}
-
 impl UserUpdateRequest {
     pub fn new(
         id: impl Into<String>,
@@ -87,17 +61,6 @@
     }
 }
 
-#[into_request(TeaclaveAuthenticationApiResponse::UserUpdate)]
-#[derive(Debug, Default)]
-pub struct UserUpdateResponse;
-
-#[into_request(TeaclaveAuthenticationApiRequest::UserLogin)]
-#[derive(Debug)]
-pub struct UserLoginRequest {
-    pub id: std::string::String,
-    pub password: std::string::String,
-}
-
 impl UserLoginRequest {
     pub fn new(id: impl Into<String>, password: impl Into<String>) -> Self {
         Self {
@@ -107,12 +70,6 @@
     }
 }
 
-#[into_request(TeaclaveAuthenticationApiResponse::UserLogin)]
-#[derive(Debug)]
-pub struct UserLoginResponse {
-    pub token: std::string::String,
-}
-
 impl UserLoginResponse {
     pub fn new(token: impl Into<String>) -> Self {
         Self {
@@ -121,12 +78,6 @@
     }
 }
 
-#[into_request(TeaclaveAuthenticationApiRequest::UserChangePassword)]
-#[derive(Debug)]
-pub struct UserChangePasswordRequest {
-    pub password: std::string::String,
-}
-
 impl UserChangePasswordRequest {
     pub fn new(password: impl Into<String>) -> Self {
         Self {
@@ -135,363 +86,42 @@
     }
 }
 
-#[into_request(TeaclaveAuthenticationApiResponse::UserChangePassword)]
-#[derive(Debug)]
-pub struct UserChangePasswordResponse {}
-
-#[into_request(TeaclaveAuthenticationApiRequest::ResetUserPassword)]
-#[derive(Debug)]
-pub struct ResetUserPasswordRequest {
-    pub id: std::string::String,
-}
-
 impl ResetUserPasswordRequest {
     pub fn new(id: impl Into<String>) -> Self {
         Self { id: id.into() }
     }
 }
 
-#[into_request(TeaclaveAuthenticationApiResponse::ResetUserPassword)]
-#[derive(Debug)]
-pub struct ResetUserPasswordResponse {
-    pub password: std::string::String,
-}
-
-#[into_request(TeaclaveAuthenticationApiRequest::DeleteUser)]
-#[derive(Debug)]
-pub struct DeleteUserRequest {
-    pub id: std::string::String,
-}
-
 impl DeleteUserRequest {
     pub fn new(id: impl Into<String>) -> Self {
         Self { id: id.into() }
     }
 }
 
-#[into_request(TeaclaveAuthenticationApiResponse::DeleteUser)]
-#[derive(Debug)]
-pub struct DeleteUserResponse {}
-
-#[into_request(TeaclaveAuthenticationApiRequest::ListUsers)]
-#[derive(Debug)]
-pub struct ListUsersRequest {
-    pub id: std::string::String,
-}
-
 impl ListUsersRequest {
     pub fn new(id: impl Into<String>) -> Self {
         Self { id: id.into() }
     }
 }
 
-#[into_request(TeaclaveAuthenticationApiResponse::ListUsers)]
-#[derive(Debug)]
-pub struct ListUsersResponse {
-    pub ids: Vec<std::string::String>,
-}
-
 impl ListUsersResponse {
     pub fn new(ids: Vec<std::string::String>) -> Self {
         Self { ids }
     }
 }
 
-#[into_request(TeaclaveAuthenticationInternalRequest::UserAuthenticate)]
-#[derive(Debug)]
-pub struct UserAuthenticateRequest {
-    pub credential: teaclave_common::UserCredential,
-}
-
 impl UserAuthenticateRequest {
     pub fn new(credential: teaclave_common::UserCredential) -> Self {
-        Self { credential }
+        Self {
+            credential: Some(credential),
+        }
     }
 }
 
-#[into_request(TeaclaveAuthenticationInternalResponse::UserAuthenticate)]
-#[derive(Debug)]
-pub struct UserAuthenticateResponse {
-    pub claims: UserAuthClaims,
-}
-
 impl UserAuthenticateResponse {
     pub fn new(claims: UserAuthClaims) -> Self {
-        Self { claims }
-    }
-}
-
-impl std::convert::TryFrom<proto::UserRegisterRequest> for UserRegisterRequest {
-    type Error = Error;
-
-    fn try_from(proto: proto::UserRegisterRequest) -> Result<Self> {
-        let ret = Self {
-            id: proto.id,
-            password: proto.password,
-            role: proto.role,
-            attribute: proto.attribute,
-        };
-
-        Ok(ret)
-    }
-}
-
-impl From<UserRegisterRequest> for proto::UserRegisterRequest {
-    fn from(request: UserRegisterRequest) -> Self {
         Self {
-            id: request.id,
-            password: request.password,
-            role: request.role,
-            attribute: request.attribute,
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::UserRegisterResponse> for UserRegisterResponse {
-    type Error = Error;
-
-    fn try_from(_reponse: proto::UserRegisterResponse) -> Result<Self> {
-        Ok(Self {})
-    }
-}
-
-impl From<UserRegisterResponse> for proto::UserRegisterResponse {
-    fn from(_response: UserRegisterResponse) -> Self {
-        Self {}
-    }
-}
-
-impl std::convert::TryFrom<proto::UserUpdateRequest> for UserUpdateRequest {
-    type Error = Error;
-
-    fn try_from(proto: proto::UserUpdateRequest) -> Result<Self> {
-        let ret = Self {
-            id: proto.id,
-            password: proto.password,
-            role: proto.role,
-            attribute: proto.attribute,
-        };
-
-        Ok(ret)
-    }
-}
-
-impl From<UserUpdateRequest> for proto::UserUpdateRequest {
-    fn from(request: UserUpdateRequest) -> Self {
-        Self {
-            id: request.id,
-            password: request.password,
-            role: request.role,
-            attribute: request.attribute,
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::UserUpdateResponse> for UserUpdateResponse {
-    type Error = Error;
-
-    fn try_from(_reponse: proto::UserUpdateResponse) -> Result<Self> {
-        Ok(Self {})
-    }
-}
-
-impl From<UserUpdateResponse> for proto::UserUpdateResponse {
-    fn from(_response: UserUpdateResponse) -> Self {
-        Self {}
-    }
-}
-
-impl std::convert::TryFrom<proto::UserLoginRequest> for UserLoginRequest {
-    type Error = Error;
-
-    fn try_from(proto: proto::UserLoginRequest) -> Result<Self> {
-        let ret = Self {
-            id: proto.id,
-            password: proto.password,
-        };
-
-        Ok(ret)
-    }
-}
-
-impl From<UserLoginRequest> for proto::UserLoginRequest {
-    fn from(request: UserLoginRequest) -> Self {
-        Self {
-            id: request.id,
-            password: request.password,
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::UserLoginResponse> for UserLoginResponse {
-    type Error = Error;
-
-    fn try_from(proto: proto::UserLoginResponse) -> Result<Self> {
-        let ret = Self { token: proto.token };
-
-        Ok(ret)
-    }
-}
-
-impl From<UserLoginResponse> for proto::UserLoginResponse {
-    fn from(response: UserLoginResponse) -> Self {
-        Self {
-            token: response.token,
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::UserChangePasswordRequest> for UserChangePasswordRequest {
-    type Error = Error;
-
-    fn try_from(proto: proto::UserChangePasswordRequest) -> Result<Self> {
-        let ret = Self {
-            password: proto.password,
-        };
-
-        Ok(ret)
-    }
-}
-
-impl From<UserChangePasswordRequest> for proto::UserChangePasswordRequest {
-    fn from(request: UserChangePasswordRequest) -> Self {
-        Self {
-            password: request.password,
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::UserChangePasswordResponse> for UserChangePasswordResponse {
-    type Error = Error;
-
-    fn try_from(_reponse: proto::UserChangePasswordResponse) -> Result<Self> {
-        Ok(Self {})
-    }
-}
-
-impl From<UserChangePasswordResponse> for proto::UserChangePasswordResponse {
-    fn from(_response: UserChangePasswordResponse) -> Self {
-        Self {}
-    }
-}
-
-impl std::convert::TryFrom<proto::ResetUserPasswordRequest> for ResetUserPasswordRequest {
-    type Error = Error;
-
-    fn try_from(proto: proto::ResetUserPasswordRequest) -> Result<Self> {
-        let ret = Self { id: proto.id };
-
-        Ok(ret)
-    }
-}
-
-impl From<ResetUserPasswordRequest> for proto::ResetUserPasswordRequest {
-    fn from(request: ResetUserPasswordRequest) -> Self {
-        Self { id: request.id }
-    }
-}
-
-impl std::convert::TryFrom<proto::ResetUserPasswordResponse> for ResetUserPasswordResponse {
-    type Error = Error;
-
-    fn try_from(proto: proto::ResetUserPasswordResponse) -> Result<Self> {
-        let ret = Self {
-            password: proto.password,
-        };
-
-        Ok(ret)
-    }
-}
-
-impl From<ResetUserPasswordResponse> for proto::ResetUserPasswordResponse {
-    fn from(response: ResetUserPasswordResponse) -> Self {
-        Self {
-            password: response.password,
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::DeleteUserRequest> for DeleteUserRequest {
-    type Error = Error;
-
-    fn try_from(proto: proto::DeleteUserRequest) -> Result<Self> {
-        let ret = Self { id: proto.id };
-
-        Ok(ret)
-    }
-}
-
-impl From<DeleteUserRequest> for proto::DeleteUserRequest {
-    fn from(request: DeleteUserRequest) -> Self {
-        Self { id: request.id }
-    }
-}
-
-impl std::convert::TryFrom<proto::DeleteUserResponse> for DeleteUserResponse {
-    type Error = Error;
-
-    fn try_from(_reponse: proto::DeleteUserResponse) -> Result<Self> {
-        Ok(Self {})
-    }
-}
-
-impl From<DeleteUserResponse> for proto::DeleteUserResponse {
-    fn from(_response: DeleteUserResponse) -> Self {
-        Self {}
-    }
-}
-
-impl std::convert::TryFrom<proto::ListUsersRequest> for ListUsersRequest {
-    type Error = Error;
-
-    fn try_from(proto: proto::ListUsersRequest) -> Result<Self> {
-        let ret = Self { id: proto.id };
-
-        Ok(ret)
-    }
-}
-
-impl From<ListUsersRequest> for proto::ListUsersRequest {
-    fn from(request: ListUsersRequest) -> Self {
-        Self { id: request.id }
-    }
-}
-
-impl std::convert::TryFrom<proto::ListUsersResponse> for ListUsersResponse {
-    type Error = Error;
-
-    fn try_from(proto: proto::ListUsersResponse) -> Result<Self> {
-        let ret = Self { ids: proto.ids };
-
-        Ok(ret)
-    }
-}
-
-impl From<ListUsersResponse> for proto::ListUsersResponse {
-    fn from(response: ListUsersResponse) -> Self {
-        Self { ids: response.ids }
-    }
-}
-
-impl std::convert::TryFrom<proto::UserAuthenticateRequest> for UserAuthenticateRequest {
-    type Error = Error;
-
-    fn try_from(proto: proto::UserAuthenticateRequest) -> Result<Self> {
-        let ret = Self {
-            credential: proto
-                .credential
-                .ok_or_else(|| anyhow!("Missing credential"))?
-                .try_into()?,
-        };
-
-        Ok(ret)
-    }
-}
-
-impl From<UserAuthenticateRequest> for proto::UserAuthenticateRequest {
-    fn from(request: UserAuthenticateRequest) -> Self {
-        Self {
-            credential: Some(request.credential.into()),
+            claims: Some(claims.into()),
         }
     }
 }
@@ -521,26 +151,3 @@
         }
     }
 }
-
-impl std::convert::TryFrom<proto::UserAuthenticateResponse> for UserAuthenticateResponse {
-    type Error = Error;
-
-    fn try_from(proto: proto::UserAuthenticateResponse) -> Result<Self> {
-        let ret = Self {
-            claims: proto
-                .claims
-                .ok_or_else(|| anyhow!("Missing claims"))?
-                .try_into()?,
-        };
-
-        Ok(ret)
-    }
-}
-
-impl From<UserAuthenticateResponse> for proto::UserAuthenticateResponse {
-    fn from(response: UserAuthenticateResponse) -> Self {
-        Self {
-            claims: Some(response.claims.into()),
-        }
-    }
-}
diff --git a/services/proto/src/teaclave_common.rs b/services/proto/src/teaclave_common.rs
index c36ceaf..a5ba494 100644
--- a/services/proto/src/teaclave_common.rs
+++ b/services/proto/src/teaclave_common.rs
@@ -17,16 +17,11 @@
 
 use crate::teaclave_common_proto as proto;
 use anyhow::{bail, Error, Result};
+pub use proto::*;
 use std::convert::TryInto;
 use teaclave_crypto::TeaclaveFile128Key;
 use teaclave_types::{FileCrypto, TaskFailure, TaskOutputs, TaskResult, TaskStatus};
 
-#[derive(Debug)]
-pub struct UserCredential {
-    pub id: std::string::String,
-    pub token: std::string::String,
-}
-
 impl UserCredential {
     pub fn new(id: impl Into<String>, token: impl Into<String>) -> Self {
         Self {
@@ -36,28 +31,6 @@
     }
 }
 
-impl std::convert::TryFrom<proto::UserCredential> for UserCredential {
-    type Error = Error;
-
-    fn try_from(proto: proto::UserCredential) -> Result<Self> {
-        let ret = Self {
-            id: proto.id,
-            token: proto.token,
-        };
-
-        Ok(ret)
-    }
-}
-
-impl From<UserCredential> for proto::UserCredential {
-    fn from(request: UserCredential) -> Self {
-        Self {
-            id: request.id,
-            token: request.token,
-        }
-    }
-}
-
 impl std::convert::TryFrom<proto::FileCryptoInfo> for FileCrypto {
     type Error = Error;
     fn try_from(proto: proto::FileCryptoInfo) -> Result<Self> {
diff --git a/services/proto/src/teaclave_frontend_service.rs b/services/proto/src/teaclave_frontend_service.rs
index ce3c26c..8f50219 100644
--- a/services/proto/src/teaclave_frontend_service.rs
+++ b/services/proto/src/teaclave_frontend_service.rs
@@ -15,282 +15,156 @@
 // specific language governing permissions and limitations
 // under the License.
 
-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;
-use anyhow::anyhow;
 use anyhow::{Error, Result};
 use core::convert::TryInto;
 use std::collections::HashMap;
-use teaclave_rpc::into_request;
 use teaclave_types::{
     Executor, ExecutorType, ExternalID, FileAuthTag, FileCrypto, FunctionArgument,
     FunctionArguments, FunctionBuilder, FunctionInput, FunctionOutput, OwnerList, TaskFileOwners,
-    TaskResult, TaskStatus, UserID, UserList,
 };
 use url::Url;
 
-pub use proto::TeaclaveFrontend;
-pub use proto::TeaclaveFrontendClient;
-pub use proto::TeaclaveFrontendRequest;
-pub use proto::TeaclaveFrontendResponse;
-
-#[into_request(TeaclaveFrontendRequest::RegisterInputFile)]
-#[into_request(TeaclaveManagementRequest::RegisterInputFile)]
-#[derive(Debug, PartialEq)]
-pub struct RegisterInputFileRequest {
-    pub url: Url,
-    pub cmac: FileAuthTag,
-    pub crypto_info: FileCrypto,
-}
+pub use proto::teaclave_frontend_client::TeaclaveFrontendClient;
+pub use proto::teaclave_frontend_server::TeaclaveFrontend;
+pub use proto::teaclave_frontend_server::TeaclaveFrontendServer;
+pub use proto::*;
 
 impl RegisterInputFileRequest {
     pub fn new(url: Url, cmac: FileAuthTag, crypto: impl Into<FileCrypto>) -> Self {
         Self {
-            url,
-            cmac,
-            crypto_info: crypto.into(),
+            url: url.as_str().to_string(),
+            cmac: cmac.to_bytes(),
+            crypto_info: Some(crypto.into().into()),
         }
     }
 }
 
-#[into_request(TeaclaveFrontendRequest::UpdateInputFile)]
-#[into_request(TeaclaveManagementRequest::UpdateInputFile)]
-#[derive(Debug, PartialEq)]
-pub struct UpdateInputFileRequest {
-    pub data_id: ExternalID,
-    pub url: Url,
-}
-
 impl UpdateInputFileRequest {
     pub fn new(data_id: ExternalID, url: Url) -> Self {
-        Self { data_id, url }
+        Self {
+            data_id: data_id.to_string(),
+            url: url.as_str().to_string(),
+        }
     }
 }
 
-#[into_request(TeaclaveFrontendResponse::RegisterInputFile)]
-#[into_request(TeaclaveManagementResponse::RegisterInputFile)]
-#[derive(Debug, PartialEq)]
-pub struct RegisterInputFileResponse {
-    pub data_id: ExternalID,
-}
-
 impl RegisterInputFileResponse {
     pub fn new(data_id: ExternalID) -> Self {
-        Self { data_id }
+        Self {
+            data_id: data_id.to_string(),
+        }
     }
 }
 
-#[into_request(TeaclaveFrontendResponse::UpdateInputFile)]
-#[into_request(TeaclaveManagementResponse::UpdateInputFile)]
-#[derive(Debug, PartialEq)]
-pub struct UpdateInputFileResponse {
-    pub data_id: ExternalID,
-}
-
 impl UpdateInputFileResponse {
     pub fn new(data_id: ExternalID) -> Self {
-        Self { data_id }
+        Self {
+            data_id: data_id.to_string(),
+        }
     }
 }
 
-#[into_request(TeaclaveFrontendRequest::RegisterOutputFile)]
-#[into_request(TeaclaveManagementRequest::RegisterOutputFile)]
-#[derive(Debug)]
-pub struct RegisterOutputFileRequest {
-    pub url: Url,
-    pub crypto_info: FileCrypto,
-}
-
 impl RegisterOutputFileRequest {
     pub fn new(url: Url, crypto: impl Into<FileCrypto>) -> Self {
         Self {
-            url,
-            crypto_info: crypto.into(),
+            url: url.as_str().to_string(),
+            crypto_info: Some(crypto.into().into()),
         }
     }
 }
 
-#[into_request(TeaclaveFrontendRequest::UpdateOutputFile)]
-#[into_request(TeaclaveManagementRequest::UpdateOutputFile)]
-#[derive(Debug)]
-pub struct UpdateOutputFileRequest {
-    pub data_id: ExternalID,
-    pub url: Url,
-}
-
 impl UpdateOutputFileRequest {
     pub fn new(data_id: ExternalID, url: Url) -> Self {
-        Self { data_id, url }
+        Self {
+            data_id: data_id.to_string(),
+            url: url.as_str().to_string(),
+        }
     }
 }
 
-#[into_request(TeaclaveFrontendResponse::RegisterOutputFile)]
-#[into_request(TeaclaveManagementResponse::RegisterOutputFile)]
-#[derive(Debug)]
-pub struct RegisterOutputFileResponse {
-    pub data_id: ExternalID,
-}
-
 impl RegisterOutputFileResponse {
     pub fn new(data_id: ExternalID) -> Self {
-        Self { data_id }
+        Self {
+            data_id: data_id.to_string(),
+        }
     }
 }
 
-#[into_request(TeaclaveFrontendResponse::UpdateOutputFile)]
-#[into_request(TeaclaveManagementResponse::UpdateOutputFile)]
-#[derive(Debug)]
-pub struct UpdateOutputFileResponse {
-    pub data_id: ExternalID,
-}
-
 impl UpdateOutputFileResponse {
     pub fn new(data_id: ExternalID) -> Self {
-        Self { data_id }
+        Self {
+            data_id: data_id.to_string(),
+        }
     }
 }
 
-#[into_request(TeaclaveFrontendRequest::RegisterFusionOutput)]
-#[into_request(TeaclaveManagementRequest::RegisterFusionOutput)]
-#[derive(Debug)]
-pub struct RegisterFusionOutputRequest {
-    pub owner_list: OwnerList,
-}
-
 impl RegisterFusionOutputRequest {
     pub fn new(owner_list: impl Into<OwnerList>) -> Self {
         Self {
-            owner_list: owner_list.into(),
+            owner_list: owner_list.into().into(),
         }
     }
 }
 
-#[into_request(TeaclaveFrontendResponse::RegisterFusionOutput)]
-#[into_request(TeaclaveManagementResponse::RegisterFusionOutput)]
-#[derive(Debug)]
-pub struct RegisterFusionOutputResponse {
-    pub data_id: ExternalID,
-}
-
 impl RegisterFusionOutputResponse {
     pub fn new(data_id: ExternalID) -> Self {
-        Self { data_id }
+        Self {
+            data_id: data_id.to_string(),
+        }
     }
 }
 
-#[into_request(TeaclaveFrontendRequest::RegisterInputFromOutput)]
-#[into_request(TeaclaveManagementRequest::RegisterInputFromOutput)]
-#[derive(Debug)]
-pub struct RegisterInputFromOutputRequest {
-    pub data_id: ExternalID,
-}
-
 impl RegisterInputFromOutputRequest {
     pub fn new(data_id: ExternalID) -> Self {
-        Self { data_id }
+        Self {
+            data_id: data_id.to_string(),
+        }
     }
 }
 
-#[into_request(TeaclaveFrontendResponse::RegisterInputFromOutput)]
-#[into_request(TeaclaveManagementResponse::RegisterInputFromOutput)]
-#[derive(Debug)]
-pub struct RegisterInputFromOutputResponse {
-    pub data_id: ExternalID,
-}
-
 impl RegisterInputFromOutputResponse {
     pub fn new(data_id: ExternalID) -> Self {
-        Self { data_id }
+        Self {
+            data_id: data_id.to_string(),
+        }
     }
 }
 
-#[into_request(TeaclaveFrontendRequest::GetInputFile)]
-#[into_request(TeaclaveManagementRequest::GetInputFile)]
-#[derive(Debug)]
-pub struct GetInputFileRequest {
-    pub data_id: ExternalID,
-}
-
 impl GetInputFileRequest {
     pub fn new(data_id: ExternalID) -> Self {
-        Self { data_id }
+        Self {
+            data_id: data_id.to_string(),
+        }
     }
 }
 
-#[into_request(TeaclaveFrontendResponse::GetInputFile)]
-#[into_request(TeaclaveManagementResponse::GetInputFile)]
-#[derive(Debug)]
-pub struct GetInputFileResponse {
-    pub owner: OwnerList,
-    pub cmac: FileAuthTag,
-}
-
 impl GetInputFileResponse {
     pub fn new(owner: OwnerList, cmac: FileAuthTag) -> Self {
-        Self { owner, cmac }
+        Self {
+            owner: owner.into(),
+            cmac: cmac.to_bytes(),
+        }
     }
 }
 
-#[into_request(TeaclaveFrontendRequest::GetOutputFile)]
-#[into_request(TeaclaveManagementRequest::GetOutputFile)]
-#[derive(Debug)]
-pub struct GetOutputFileRequest {
-    pub data_id: ExternalID,
-}
-
 impl GetOutputFileRequest {
     pub fn new(data_id: ExternalID) -> Self {
-        Self { data_id }
+        Self {
+            data_id: data_id.to_string(),
+        }
     }
 }
 
-#[into_request(TeaclaveFrontendResponse::GetOutputFile)]
-#[into_request(TeaclaveManagementResponse::GetOutputFile)]
-#[derive(Debug)]
-pub struct GetOutputFileResponse {
-    pub owner: OwnerList,
-    pub cmac: Option<FileAuthTag>,
-}
-
 impl GetOutputFileResponse {
     pub fn new(owner: OwnerList, cmac: Option<FileAuthTag>) -> Self {
-        Self { owner, cmac }
+        Self {
+            owner: owner.into(),
+            cmac: cmac.map_or_else(Vec::new, |cmac| cmac.to_bytes()),
+        }
     }
 }
 
-#[into_request(TeaclaveManagementRequest::ListFunctions)]
-#[into_request(TeaclaveFrontendRequest::ListFunctions)]
-#[derive(Debug, Default)]
-pub struct ListFunctionsRequest {
-    pub user_id: UserID,
-}
-
-#[into_request(TeaclaveManagementResponse::ListFunctions)]
-#[into_request(TeaclaveFrontendResponse::ListFunctions)]
-#[derive(Debug, Default)]
-pub struct ListFunctionsResponse {
-    pub registered_functions: Vec<String>,
-    pub allowed_functions: Vec<String>,
-}
-
-#[into_request(TeaclaveManagementRequest::RegisterFunction)]
-#[into_request(TeaclaveFrontendRequest::RegisterFunction)]
-#[derive(Debug, Default)]
-pub struct RegisterFunctionRequest {
-    pub name: String,
-    pub description: String,
-    pub executor_type: ExecutorType,
-    pub payload: Vec<u8>,
-    pub public: bool,
-    pub arguments: Vec<FunctionArgument>,
-    pub inputs: Vec<FunctionInput>,
-    pub outputs: Vec<FunctionOutput>,
-    pub user_allowlist: Vec<String>,
-    pub usage_quota: Option<i32>,
-}
-
 #[derive(Default)]
 pub struct RegisterFunctionRequestBuilder {
     request: RegisterFunctionRequest,
@@ -299,8 +173,9 @@
 impl RegisterFunctionRequestBuilder {
     pub fn new() -> Self {
         let request = RegisterFunctionRequest {
-            executor_type: ExecutorType::Builtin,
+            executor_type: ExecutorType::Builtin.to_string(),
             public: true,
+            usage_quota: -1,
             ..Default::default()
         };
 
@@ -318,7 +193,7 @@
     }
 
     pub fn executor_type(mut self, executor_type: ExecutorType) -> Self {
-        self.request.executor_type = executor_type;
+        self.request.executor_type = executor_type.to_string();
         self
     }
 
@@ -333,17 +208,17 @@
     }
 
     pub fn arguments(mut self, args: Vec<FunctionArgument>) -> Self {
-        self.request.arguments = args;
+        self.request.arguments = args.into_iter().map(|x| x.into()).collect();
         self
     }
 
     pub fn inputs(mut self, inputs: Vec<FunctionInput>) -> Self {
-        self.request.inputs = inputs;
+        self.request.inputs = inputs.into_iter().map(|x| x.into()).collect();
         self
     }
 
     pub fn outputs(mut self, outputs: Vec<FunctionOutput>) -> Self {
-        self.request.outputs = outputs;
+        self.request.outputs = outputs.into_iter().map(|x| x.into()).collect();
         self
     }
 
@@ -353,7 +228,7 @@
     }
 
     pub fn usage_quota(mut self, usage_quota: Option<i32>) -> Self {
-        self.request.usage_quota = usage_quota;
+        self.request.usage_quota = usage_quota.unwrap_or(-1);
         self
     }
 
@@ -363,51 +238,49 @@
 }
 
 // We explicitly construct Function here in case of missing any field
-impl From<RegisterFunctionRequest> for FunctionBuilder {
-    fn from(request: RegisterFunctionRequest) -> Self {
-        FunctionBuilder::new()
+impl std::convert::TryFrom<RegisterFunctionRequest> for FunctionBuilder {
+    type Error = Error;
+    fn try_from(request: RegisterFunctionRequest) -> Result<Self> {
+        Ok(FunctionBuilder::new()
             .name(request.name)
             .description(request.description)
             .public(request.public)
-            .executor_type(request.executor_type)
+            .executor_type(request.executor_type.try_into()?)
             .payload(request.payload)
-            .arguments(request.arguments)
-            .inputs(request.inputs)
-            .outputs(request.outputs)
+            .arguments(
+                request
+                    .arguments
+                    .into_iter()
+                    .map(FunctionArgument::try_from)
+                    .collect::<Result<_>>()?,
+            )
+            .inputs(
+                request
+                    .inputs
+                    .into_iter()
+                    .map(FunctionInput::try_from)
+                    .collect::<Result<_>>()?,
+            )
+            .outputs(
+                request
+                    .outputs
+                    .into_iter()
+                    .map(FunctionOutput::try_from)
+                    .collect::<Result<_>>()?,
+            )
             .user_allowlist(request.user_allowlist)
-            .usage_quota(request.usage_quota)
+            .usage_quota((request.usage_quota >= 0).then_some(request.usage_quota)))
     }
 }
 
-#[into_request(TeaclaveManagementResponse::RegisterFunction)]
-#[derive(Debug)]
-pub struct RegisterFunctionResponse {
-    pub function_id: ExternalID,
-}
-
 impl RegisterFunctionResponse {
     pub fn new(function_id: ExternalID) -> Self {
-        Self { function_id }
+        Self {
+            function_id: function_id.to_string(),
+        }
     }
 }
 
-#[into_request(TeaclaveManagementRequest::UpdateFunction)]
-#[into_request(TeaclaveFrontendRequest::UpdateFunction)]
-#[derive(Debug, Default)]
-pub struct UpdateFunctionRequest {
-    pub function_id: ExternalID,
-    pub name: String,
-    pub description: String,
-    pub executor_type: ExecutorType,
-    pub payload: Vec<u8>,
-    pub public: bool,
-    pub arguments: Vec<FunctionArgument>,
-    pub inputs: Vec<FunctionInput>,
-    pub outputs: Vec<FunctionOutput>,
-    pub user_allowlist: Vec<String>,
-    pub usage_quota: Option<i32>,
-}
-
 #[derive(Default)]
 pub struct UpdateFunctionRequestBuilder {
     request: UpdateFunctionRequest,
@@ -416,8 +289,9 @@
 impl UpdateFunctionRequestBuilder {
     pub fn new() -> Self {
         let request = UpdateFunctionRequest {
-            executor_type: ExecutorType::Builtin,
+            executor_type: ExecutorType::Builtin.to_string(),
             public: true,
+            usage_quota: -1,
             ..Default::default()
         };
 
@@ -425,7 +299,7 @@
     }
 
     pub fn function_id(mut self, id: ExternalID) -> Self {
-        self.request.function_id = id;
+        self.request.function_id = id.to_string();
         self
     }
 
@@ -440,7 +314,7 @@
     }
 
     pub fn executor_type(mut self, executor_type: ExecutorType) -> Self {
-        self.request.executor_type = executor_type;
+        self.request.executor_type = executor_type.to_string();
         self
     }
 
@@ -455,17 +329,23 @@
     }
 
     pub fn arguments(mut self, args: Vec<FunctionArgument>) -> Self {
-        self.request.arguments = args;
+        self.request.arguments = args
+            .into_iter()
+            .map(proto::FunctionArgument::from)
+            .collect();
         self
     }
 
     pub fn inputs(mut self, inputs: Vec<FunctionInput>) -> Self {
-        self.request.inputs = inputs;
+        self.request.inputs = inputs.into_iter().map(proto::FunctionInput::from).collect();
         self
     }
 
     pub fn outputs(mut self, outputs: Vec<FunctionOutput>) -> Self {
-        self.request.outputs = outputs;
+        self.request.outputs = outputs
+            .into_iter()
+            .map(proto::FunctionOutput::from)
+            .collect();
         self
     }
 
@@ -475,7 +355,7 @@
     }
 
     pub fn usage_quota(mut self, usage_quota: Option<i32>) -> Self {
-        self.request.usage_quota = usage_quota;
+        self.request.usage_quota = usage_quota.unwrap_or(-1);
         self
     }
 
@@ -485,605 +365,180 @@
 }
 
 // We explicitly construct Function here in case of missing any field
-impl From<UpdateFunctionRequest> for FunctionBuilder {
-    fn from(request: UpdateFunctionRequest) -> Self {
-        FunctionBuilder::new()
-            .id(request.function_id.uuid)
+impl std::convert::TryFrom<UpdateFunctionRequest> for FunctionBuilder {
+    type Error = Error;
+    fn try_from(request: UpdateFunctionRequest) -> Result<Self> {
+        let function_id: ExternalID = request.function_id.try_into()?;
+        Ok(FunctionBuilder::new()
+            .id(function_id.uuid)
             .name(request.name)
             .description(request.description)
             .public(request.public)
-            .executor_type(request.executor_type)
+            .executor_type(request.executor_type.try_into()?)
             .payload(request.payload)
-            .arguments(request.arguments)
-            .inputs(request.inputs)
-            .outputs(request.outputs)
+            .arguments(
+                request
+                    .arguments
+                    .into_iter()
+                    .map(FunctionArgument::try_from)
+                    .collect::<Result<_>>()?,
+            )
+            .inputs(
+                request
+                    .inputs
+                    .into_iter()
+                    .map(FunctionInput::try_from)
+                    .collect::<Result<_>>()?,
+            )
+            .outputs(
+                request
+                    .outputs
+                    .into_iter()
+                    .map(FunctionOutput::try_from)
+                    .collect::<Result<_>>()?,
+            )
             .user_allowlist(request.user_allowlist)
-            .usage_quota(request.usage_quota)
+            .usage_quota((request.usage_quota >= 0).then_some(request.usage_quota)))
     }
 }
 
-#[into_request(TeaclaveManagementResponse::UpdateFunction)]
-#[derive(Debug)]
-pub struct UpdateFunctionResponse {
-    pub function_id: ExternalID,
-}
-
 impl UpdateFunctionResponse {
     pub fn new(function_id: ExternalID) -> Self {
-        Self { function_id }
+        Self {
+            function_id: function_id.to_string(),
+        }
     }
 }
 
-#[into_request(TeaclaveManagementRequest::GetFunction)]
-#[into_request(TeaclaveFrontendRequest::GetFunction)]
-#[derive(Debug)]
-pub struct GetFunctionRequest {
-    pub function_id: ExternalID,
-}
-
 impl GetFunctionRequest {
     pub fn new(function_id: ExternalID) -> Self {
-        Self { function_id }
+        Self {
+            function_id: function_id.to_string(),
+        }
     }
 }
 
-#[into_request(TeaclaveManagementResponse::GetFunction)]
-#[derive(Debug)]
-pub struct GetFunctionResponse {
-    pub name: String,
-    pub description: String,
-    pub owner: UserID,
-    pub payload: Vec<u8>,
-    pub public: bool,
-    pub executor_type: ExecutorType,
-    pub arguments: Vec<FunctionArgument>,
-    pub inputs: Vec<FunctionInput>,
-    pub outputs: Vec<FunctionOutput>,
-    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 }
+        Self {
+            function_id: function_id.to_string(),
+        }
     }
 }
 
-#[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)]
-pub struct DeleteFunctionRequest {
-    pub function_id: ExternalID,
-}
-
 impl DeleteFunctionRequest {
     pub fn new(function_id: ExternalID) -> Self {
-        Self { function_id }
+        Self {
+            function_id: function_id.to_string(),
+        }
     }
 }
 
-#[into_request(TeaclaveManagementResponse::DeleteFunction)]
-#[derive(Debug)]
-pub struct DeleteFunctionResponse {}
-
-#[into_request(TeaclaveManagementRequest::DisableFunction)]
-#[into_request(TeaclaveFrontendRequest::DisableFunction)]
-#[derive(Debug)]
-pub struct DisableFunctionRequest {
-    pub function_id: ExternalID,
-}
-
 impl DisableFunctionRequest {
     pub fn new(function_id: ExternalID) -> Self {
-        Self { function_id }
+        Self {
+            function_id: function_id.to_string(),
+        }
     }
 }
 
-#[into_request(TeaclaveManagementResponse::DisableFunction)]
-#[derive(Debug)]
-pub struct DisableFunctionResponse {}
-
-#[into_request(TeaclaveManagementRequest::CreateTask)]
-#[into_request(TeaclaveFrontendRequest::CreateTask)]
-#[derive(Default)]
-pub struct CreateTaskRequest {
-    pub function_id: ExternalID,
-    pub function_arguments: FunctionArguments,
-    pub executor: Executor,
-    pub inputs_ownership: TaskFileOwners,
-    pub outputs_ownership: TaskFileOwners,
-}
-
 impl CreateTaskRequest {
     pub fn new() -> Self {
-        Self::default()
+        Self {
+            executor: Executor::default().to_string(),
+            function_arguments: FunctionArguments::default().into_string(),
+            ..Default::default()
+        }
     }
 
     pub fn function_id(self, function_id: ExternalID) -> Self {
         Self {
-            function_id,
+            function_id: function_id.to_string(),
             ..self
         }
     }
 
     pub fn function_arguments(self, function_arguments: impl Into<FunctionArguments>) -> Self {
         Self {
-            function_arguments: function_arguments.into(),
+            function_arguments: function_arguments.into().into_string(),
             ..self
         }
     }
 
     pub fn executor(self, executor: Executor) -> Self {
-        Self { executor, ..self }
+        Self {
+            executor: executor.to_string(),
+            ..self
+        }
     }
 
     pub fn inputs_ownership(self, map: impl Into<TaskFileOwners>) -> Self {
         Self {
-            inputs_ownership: map.into(),
+            inputs_ownership: to_proto_ownership(map.into()),
             ..self
         }
     }
 
     pub fn outputs_ownership(self, map: impl Into<TaskFileOwners>) -> Self {
         Self {
-            outputs_ownership: map.into(),
+            outputs_ownership: to_proto_ownership(map.into()),
             ..self
         }
     }
 }
 
-#[into_request(TeaclaveManagementResponse::CreateTask)]
-#[derive(Debug)]
-pub struct CreateTaskResponse {
-    pub task_id: ExternalID,
-}
-
 impl CreateTaskResponse {
     pub fn new(task_id: ExternalID) -> Self {
-        Self { task_id }
+        Self {
+            task_id: task_id.to_string(),
+        }
     }
 }
 
-#[into_request(TeaclaveManagementRequest::GetTask)]
-#[into_request(TeaclaveFrontendRequest::GetTask)]
-#[derive(Debug)]
-pub struct GetTaskRequest {
-    pub task_id: ExternalID,
-}
-
 impl GetTaskRequest {
     pub fn new(task_id: ExternalID) -> Self {
-        Self { task_id }
+        Self {
+            task_id: task_id.to_string(),
+        }
     }
 }
 
-#[into_request(TeaclaveManagementResponse::GetTask)]
-#[derive(Debug)]
-pub struct GetTaskResponse {
-    pub task_id: ExternalID,
-    pub creator: UserID,
-    pub function_id: ExternalID,
-    pub function_owner: UserID,
-    pub function_arguments: FunctionArguments,
-    pub inputs_ownership: TaskFileOwners,
-    pub outputs_ownership: TaskFileOwners,
-    pub participants: UserList,
-    pub approved_users: UserList,
-    pub assigned_inputs: HashMap<String, ExternalID>,
-    pub assigned_outputs: HashMap<String, ExternalID>,
-    pub status: TaskStatus,
-    pub result: TaskResult,
-}
-
-#[into_request(TeaclaveManagementRequest::AssignData)]
-#[into_request(TeaclaveFrontendRequest::AssignData)]
-#[derive(Debug)]
-pub struct AssignDataRequest {
-    pub task_id: ExternalID,
-    pub inputs: HashMap<String, ExternalID>,
-    pub outputs: HashMap<String, ExternalID>,
-}
-
 impl AssignDataRequest {
     pub fn new(
         task_id: ExternalID,
         inputs: HashMap<String, ExternalID>,
         outputs: HashMap<String, ExternalID>,
     ) -> Self {
+        let inputs = to_proto_file_ids(inputs);
+        let outputs = to_proto_file_ids(outputs);
         Self {
-            task_id,
+            task_id: task_id.to_string(),
             inputs,
             outputs,
         }
     }
 }
 
-#[derive(Debug)]
-pub struct AssignDataResponse;
-
-#[into_request(TeaclaveManagementRequest::ApproveTask)]
-#[into_request(TeaclaveFrontendRequest::ApproveTask)]
-#[derive(Debug)]
-pub struct ApproveTaskRequest {
-    pub task_id: ExternalID,
-}
-
 impl ApproveTaskRequest {
     pub fn new(task_id: ExternalID) -> Self {
-        Self { task_id }
+        Self {
+            task_id: task_id.to_string(),
+        }
     }
 }
 
-#[derive(Debug)]
-pub struct ApproveTaskResponse;
-
-#[into_request(TeaclaveManagementRequest::InvokeTask)]
-#[into_request(TeaclaveFrontendRequest::InvokeTask)]
-#[derive(Debug)]
-pub struct InvokeTaskRequest {
-    pub task_id: ExternalID,
-}
-
 impl InvokeTaskRequest {
     pub fn new(task_id: ExternalID) -> Self {
-        Self { task_id }
+        Self {
+            task_id: task_id.to_string(),
+        }
     }
 }
 
-#[derive(Debug)]
-pub struct InvokeTaskResponse;
-
-#[into_request(TeaclaveManagementRequest::CancelTask)]
-#[into_request(TeaclaveFrontendRequest::CancelTask)]
-#[derive(Debug)]
-pub struct CancelTaskRequest {
-    pub task_id: ExternalID,
-}
-
 impl CancelTaskRequest {
     pub fn new(task_id: ExternalID) -> Self {
-        Self { task_id }
-    }
-}
-
-#[derive(Debug)]
-pub struct CancelTaskResponse;
-
-impl std::convert::TryFrom<proto::RegisterInputFileRequest> for RegisterInputFileRequest {
-    type Error = Error;
-
-    fn try_from(proto: proto::RegisterInputFileRequest) -> Result<Self> {
-        let url = Url::parse(&proto.url)?;
-        let cmac = FileAuthTag::from_bytes(&proto.cmac)?;
-        let crypto_info = proto
-            .crypto_info
-            .ok_or_else(|| anyhow!("missing crypto_info"))?
-            .try_into()?;
-        Ok(RegisterInputFileRequest {
-            url,
-            cmac,
-            crypto_info,
-        })
-    }
-}
-
-impl From<RegisterInputFileRequest> for proto::RegisterInputFileRequest {
-    fn from(request: RegisterInputFileRequest) -> Self {
         Self {
-            url: request.url.as_str().to_string(),
-            cmac: request.cmac.to_bytes(),
-            crypto_info: Some(request.crypto_info.into()),
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::UpdateInputFileRequest> for UpdateInputFileRequest {
-    type Error = Error;
-
-    fn try_from(proto: proto::UpdateInputFileRequest) -> Result<Self> {
-        let data_id = proto.data_id.try_into()?;
-        let url = Url::parse(&proto.url)?;
-
-        Ok(UpdateInputFileRequest { data_id, url })
-    }
-}
-
-impl From<UpdateInputFileRequest> for proto::UpdateInputFileRequest {
-    fn from(request: UpdateInputFileRequest) -> Self {
-        Self {
-            data_id: request.data_id.to_string(),
-            url: request.url.as_str().to_string(),
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::RegisterInputFileResponse> for RegisterInputFileResponse {
-    type Error = Error;
-
-    fn try_from(proto: proto::RegisterInputFileResponse) -> Result<Self> {
-        let data_id = proto.data_id.try_into()?;
-        Ok(Self { data_id })
-    }
-}
-
-impl From<RegisterInputFileResponse> for proto::RegisterInputFileResponse {
-    fn from(request: RegisterInputFileResponse) -> Self {
-        Self {
-            data_id: request.data_id.to_string(),
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::UpdateInputFileResponse> for UpdateInputFileResponse {
-    type Error = Error;
-
-    fn try_from(proto: proto::UpdateInputFileResponse) -> Result<Self> {
-        let data_id = proto.data_id.try_into()?;
-        Ok(Self { data_id })
-    }
-}
-
-impl From<UpdateInputFileResponse> for proto::UpdateInputFileResponse {
-    fn from(request: UpdateInputFileResponse) -> Self {
-        Self {
-            data_id: request.data_id.to_string(),
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::RegisterOutputFileRequest> for RegisterOutputFileRequest {
-    type Error = Error;
-
-    fn try_from(proto: proto::RegisterOutputFileRequest) -> Result<Self> {
-        let ret = Self {
-            url: Url::parse(&proto.url)?,
-            crypto_info: proto
-                .crypto_info
-                .ok_or_else(|| anyhow!("missing crypto_info"))?
-                .try_into()?,
-        };
-
-        Ok(ret)
-    }
-}
-
-impl From<RegisterOutputFileRequest> for proto::RegisterOutputFileRequest {
-    fn from(request: RegisterOutputFileRequest) -> Self {
-        Self {
-            url: request.url.as_str().to_string(),
-            crypto_info: Some(request.crypto_info.into()),
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::UpdateOutputFileRequest> for UpdateOutputFileRequest {
-    type Error = Error;
-
-    fn try_from(proto: proto::UpdateOutputFileRequest) -> Result<Self> {
-        let ret = Self {
-            data_id: proto.data_id.try_into()?,
-            url: Url::parse(&proto.url)?,
-        };
-
-        Ok(ret)
-    }
-}
-
-impl From<UpdateOutputFileRequest> for proto::UpdateOutputFileRequest {
-    fn from(request: UpdateOutputFileRequest) -> Self {
-        Self {
-            data_id: request.data_id.to_string(),
-            url: request.url.as_str().to_string(),
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::RegisterOutputFileResponse> for RegisterOutputFileResponse {
-    type Error = Error;
-
-    fn try_from(proto: proto::RegisterOutputFileResponse) -> Result<Self> {
-        let data_id = proto.data_id.try_into()?;
-        Ok(Self { data_id })
-    }
-}
-
-impl From<RegisterOutputFileResponse> for proto::RegisterOutputFileResponse {
-    fn from(request: RegisterOutputFileResponse) -> Self {
-        Self {
-            data_id: request.data_id.to_string(),
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::UpdateOutputFileResponse> for UpdateOutputFileResponse {
-    type Error = Error;
-
-    fn try_from(proto: proto::UpdateOutputFileResponse) -> Result<Self> {
-        let data_id = proto.data_id.try_into()?;
-        Ok(Self { data_id })
-    }
-}
-
-impl From<UpdateOutputFileResponse> for proto::UpdateOutputFileResponse {
-    fn from(request: UpdateOutputFileResponse) -> Self {
-        Self {
-            data_id: request.data_id.to_string(),
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::RegisterFusionOutputRequest> for RegisterFusionOutputRequest {
-    type Error = Error;
-
-    fn try_from(proto: proto::RegisterFusionOutputRequest) -> Result<Self> {
-        let ret = Self {
-            owner_list: OwnerList::new(proto.owner_list),
-        };
-
-        Ok(ret)
-    }
-}
-
-impl From<RegisterFusionOutputRequest> for proto::RegisterFusionOutputRequest {
-    fn from(request: RegisterFusionOutputRequest) -> Self {
-        Self {
-            owner_list: request.owner_list.into(),
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::RegisterFusionOutputResponse> for RegisterFusionOutputResponse {
-    type Error = Error;
-
-    fn try_from(proto: proto::RegisterFusionOutputResponse) -> Result<Self> {
-        let data_id = proto.data_id.try_into()?;
-        Ok(Self { data_id })
-    }
-}
-
-impl From<RegisterFusionOutputResponse> for proto::RegisterFusionOutputResponse {
-    fn from(request: RegisterFusionOutputResponse) -> Self {
-        Self {
-            data_id: request.data_id.to_string(),
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::RegisterInputFromOutputRequest>
-    for RegisterInputFromOutputRequest
-{
-    type Error = Error;
-
-    fn try_from(proto: proto::RegisterInputFromOutputRequest) -> Result<Self> {
-        let data_id = proto.data_id.try_into()?;
-        let ret = Self { data_id };
-
-        Ok(ret)
-    }
-}
-
-impl From<RegisterInputFromOutputRequest> for proto::RegisterInputFromOutputRequest {
-    fn from(request: RegisterInputFromOutputRequest) -> Self {
-        Self {
-            data_id: request.data_id.to_string(),
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::RegisterInputFromOutputResponse>
-    for RegisterInputFromOutputResponse
-{
-    type Error = Error;
-
-    fn try_from(proto: proto::RegisterInputFromOutputResponse) -> Result<Self> {
-        let data_id = proto.data_id.try_into()?;
-        Ok(Self { data_id })
-    }
-}
-
-impl From<RegisterInputFromOutputResponse> for proto::RegisterInputFromOutputResponse {
-    fn from(request: RegisterInputFromOutputResponse) -> Self {
-        Self {
-            data_id: request.data_id.to_string(),
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::GetInputFileRequest> for GetInputFileRequest {
-    type Error = Error;
-
-    fn try_from(proto: proto::GetInputFileRequest) -> Result<Self> {
-        let data_id = proto.data_id.try_into()?;
-        let ret = Self { data_id };
-
-        Ok(ret)
-    }
-}
-
-impl From<GetInputFileRequest> for proto::GetInputFileRequest {
-    fn from(request: GetInputFileRequest) -> Self {
-        Self {
-            data_id: request.data_id.to_string(),
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::GetInputFileResponse> for GetInputFileResponse {
-    type Error = Error;
-
-    fn try_from(proto: proto::GetInputFileResponse) -> Result<Self> {
-        Ok(Self {
-            owner: OwnerList::new(proto.owner),
-            cmac: FileAuthTag::from_bytes(&proto.cmac)?,
-        })
-    }
-}
-
-impl From<GetInputFileResponse> for proto::GetInputFileResponse {
-    fn from(request: GetInputFileResponse) -> Self {
-        Self {
-            owner: request.owner.into(),
-            cmac: request.cmac.to_bytes(),
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::GetOutputFileRequest> for GetOutputFileRequest {
-    type Error = Error;
-
-    fn try_from(proto: proto::GetOutputFileRequest) -> Result<Self> {
-        let data_id = proto.data_id.try_into()?;
-        let ret = Self { data_id };
-
-        Ok(ret)
-    }
-}
-
-impl From<GetOutputFileRequest> for proto::GetOutputFileRequest {
-    fn from(request: GetOutputFileRequest) -> Self {
-        Self {
-            data_id: request.data_id.to_string(),
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::GetOutputFileResponse> for GetOutputFileResponse {
-    type Error = Error;
-
-    fn try_from(proto: proto::GetOutputFileResponse) -> Result<Self> {
-        let cmac = {
-            if proto.cmac.is_empty() {
-                None
-            } else {
-                Some(FileAuthTag::from_bytes(&proto.cmac)?)
-            }
-        };
-
-        Ok(Self {
-            owner: OwnerList::new(proto.owner),
-            cmac,
-        })
-    }
-}
-
-impl From<GetOutputFileResponse> for proto::GetOutputFileResponse {
-    fn from(request: GetOutputFileResponse) -> Self {
-        Self {
-            owner: request.owner.into(),
-            cmac: request.cmac.map_or_else(Vec::new, |cmac| cmac.to_bytes()),
+            task_id: task_id.to_string(),
         }
     }
 }
@@ -1136,423 +591,6 @@
     }
 }
 
-impl std::convert::TryFrom<proto::RegisterFunctionRequest> for RegisterFunctionRequest {
-    type Error = Error;
-
-    fn try_from(proto: proto::RegisterFunctionRequest) -> Result<Self> {
-        let inputs: Result<Vec<FunctionInput>> = proto
-            .inputs
-            .into_iter()
-            .map(FunctionInput::try_from)
-            .collect();
-        let outputs: Result<Vec<FunctionOutput>> = proto
-            .outputs
-            .into_iter()
-            .map(FunctionOutput::try_from)
-            .collect();
-        let executor_type = proto.executor_type.try_into()?;
-        let arguments: Result<Vec<FunctionArgument>> = proto
-            .arguments
-            .into_iter()
-            .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,
-            executor_type,
-            payload: proto.payload,
-            public: proto.public,
-            arguments: arguments?,
-            inputs: inputs?,
-            outputs: outputs?,
-            user_allowlist: proto.user_allowlist,
-            usage_quota,
-        };
-        Ok(ret)
-    }
-}
-
-impl From<RegisterFunctionRequest> for proto::RegisterFunctionRequest {
-    fn from(request: RegisterFunctionRequest) -> Self {
-        let inputs: Vec<proto::FunctionInput> = request
-            .inputs
-            .into_iter()
-            .map(proto::FunctionInput::from)
-            .collect();
-        let outputs: Vec<proto::FunctionOutput> = request
-            .outputs
-            .into_iter()
-            .map(proto::FunctionOutput::from)
-            .collect();
-        let arguments: Vec<proto::FunctionArgument> = request
-            .arguments
-            .into_iter()
-            .map(proto::FunctionArgument::from)
-            .collect();
-
-        Self {
-            name: request.name,
-            description: request.description,
-            executor_type: request.executor_type.into(),
-            payload: request.payload,
-            public: request.public,
-            arguments,
-            inputs,
-            outputs,
-            user_allowlist: request.user_allowlist,
-            usage_quota: request.usage_quota.unwrap_or(-1),
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::RegisterFunctionResponse> for RegisterFunctionResponse {
-    type Error = Error;
-
-    fn try_from(proto: proto::RegisterFunctionResponse) -> Result<Self> {
-        let function_id = proto.function_id.try_into()?;
-        Ok(Self { function_id })
-    }
-}
-
-impl From<RegisterFunctionResponse> for proto::RegisterFunctionResponse {
-    fn from(response: RegisterFunctionResponse) -> Self {
-        Self {
-            function_id: response.function_id.to_string(),
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::UpdateFunctionRequest> for UpdateFunctionRequest {
-    type Error = Error;
-
-    fn try_from(proto: proto::UpdateFunctionRequest) -> Result<Self> {
-        let function_id = proto.function_id.try_into()?;
-        let inputs: Result<Vec<FunctionInput>> = proto
-            .inputs
-            .into_iter()
-            .map(FunctionInput::try_from)
-            .collect();
-        let outputs: Result<Vec<FunctionOutput>> = proto
-            .outputs
-            .into_iter()
-            .map(FunctionOutput::try_from)
-            .collect();
-        let executor_type = proto.executor_type.try_into()?;
-        let arguments: Result<Vec<FunctionArgument>> = proto
-            .arguments
-            .into_iter()
-            .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,
-            description: proto.description,
-            executor_type,
-            payload: proto.payload,
-            public: proto.public,
-            arguments: arguments?,
-            inputs: inputs?,
-            outputs: outputs?,
-            user_allowlist: proto.user_allowlist,
-            usage_quota,
-        };
-        Ok(ret)
-    }
-}
-
-impl From<UpdateFunctionRequest> for proto::UpdateFunctionRequest {
-    fn from(request: UpdateFunctionRequest) -> Self {
-        let inputs: Vec<proto::FunctionInput> = request
-            .inputs
-            .into_iter()
-            .map(proto::FunctionInput::from)
-            .collect();
-        let outputs: Vec<proto::FunctionOutput> = request
-            .outputs
-            .into_iter()
-            .map(proto::FunctionOutput::from)
-            .collect();
-        let arguments: Vec<proto::FunctionArgument> = request
-            .arguments
-            .into_iter()
-            .map(proto::FunctionArgument::from)
-            .collect();
-
-        Self {
-            function_id: request.function_id.to_string(),
-            name: request.name,
-            description: request.description,
-            executor_type: request.executor_type.into(),
-            payload: request.payload,
-            public: request.public,
-            arguments,
-            inputs,
-            outputs,
-            user_allowlist: request.user_allowlist,
-            usage_quota: request.usage_quota.unwrap_or(-1),
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::UpdateFunctionResponse> for UpdateFunctionResponse {
-    type Error = Error;
-
-    fn try_from(proto: proto::UpdateFunctionResponse) -> Result<Self> {
-        let function_id = proto.function_id.try_into()?;
-        let ret = Self { function_id };
-
-        Ok(ret)
-    }
-}
-
-impl From<UpdateFunctionResponse> for proto::UpdateFunctionResponse {
-    fn from(response: UpdateFunctionResponse) -> Self {
-        Self {
-            function_id: response.function_id.to_string(),
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::GetFunctionRequest> for GetFunctionRequest {
-    type Error = Error;
-
-    fn try_from(proto: proto::GetFunctionRequest) -> Result<Self> {
-        let function_id = proto.function_id.try_into()?;
-        let ret = Self { function_id };
-
-        Ok(ret)
-    }
-}
-
-impl From<GetFunctionRequest> for proto::GetFunctionRequest {
-    fn from(request: GetFunctionRequest) -> Self {
-        Self {
-            function_id: request.function_id.to_string(),
-        }
-    }
-}
-
-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;
-
-    fn try_from(_proto: proto::DeleteFunctionResponse) -> Result<Self> {
-        Ok(DeleteFunctionResponse {})
-    }
-}
-
-impl From<DeleteFunctionResponse> for proto::DeleteFunctionResponse {
-    fn from(_response: DeleteFunctionResponse) -> Self {
-        Self {}
-    }
-}
-
-impl std::convert::TryFrom<proto::DisableFunctionResponse> for DisableFunctionResponse {
-    type Error = Error;
-
-    fn try_from(_proto: proto::DisableFunctionResponse) -> Result<Self> {
-        Ok(DisableFunctionResponse {})
-    }
-}
-
-impl From<DisableFunctionResponse> for proto::DisableFunctionResponse {
-    fn from(_response: DisableFunctionResponse) -> Self {
-        Self {}
-    }
-}
-
-impl std::convert::TryFrom<proto::ListFunctionsRequest> for ListFunctionsRequest {
-    type Error = Error;
-
-    fn try_from(proto: proto::ListFunctionsRequest) -> Result<Self> {
-        let user_id = proto.user_id.try_into()?;
-        let ret = Self { user_id };
-
-        Ok(ret)
-    }
-}
-
-impl From<ListFunctionsRequest> for proto::ListFunctionsRequest {
-    fn from(request: ListFunctionsRequest) -> Self {
-        Self {
-            user_id: request.user_id.to_string(),
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::ListFunctionsResponse> for ListFunctionsResponse {
-    type Error = Error;
-
-    fn try_from(proto: proto::ListFunctionsResponse) -> Result<Self> {
-        let ret = Self {
-            registered_functions: proto.registered_functions,
-            allowed_functions: proto.allowed_functions,
-        };
-
-        Ok(ret)
-    }
-}
-
-impl From<ListFunctionsResponse> for proto::ListFunctionsResponse {
-    fn from(request: ListFunctionsResponse) -> Self {
-        Self {
-            registered_functions: request.registered_functions,
-            allowed_functions: request.allowed_functions,
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::DeleteFunctionRequest> for DeleteFunctionRequest {
-    type Error = Error;
-
-    fn try_from(proto: proto::DeleteFunctionRequest) -> Result<Self> {
-        let function_id = proto.function_id.try_into()?;
-        let ret = Self { function_id };
-
-        Ok(ret)
-    }
-}
-
-impl From<DeleteFunctionRequest> for proto::DeleteFunctionRequest {
-    fn from(request: DeleteFunctionRequest) -> Self {
-        Self {
-            function_id: request.function_id.to_string(),
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::DisableFunctionRequest> for DisableFunctionRequest {
-    type Error = Error;
-
-    fn try_from(proto: proto::DisableFunctionRequest) -> Result<Self> {
-        let function_id = proto.function_id.try_into()?;
-        let ret = Self { function_id };
-
-        Ok(ret)
-    }
-}
-
-impl From<DisableFunctionRequest> for proto::DisableFunctionRequest {
-    fn from(request: DisableFunctionRequest) -> Self {
-        Self {
-            function_id: request.function_id.to_string(),
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::GetFunctionResponse> for GetFunctionResponse {
-    type Error = Error;
-
-    fn try_from(proto: proto::GetFunctionResponse) -> Result<Self> {
-        let inputs: Result<Vec<FunctionInput>> = proto
-            .inputs
-            .into_iter()
-            .map(FunctionInput::try_from)
-            .collect();
-        let outputs: Result<Vec<FunctionOutput>> = proto
-            .outputs
-            .into_iter()
-            .map(FunctionOutput::try_from)
-            .collect();
-        let executor_type = proto.executor_type.try_into()?;
-        let arguments: Result<Vec<FunctionArgument>> = proto
-            .arguments
-            .into_iter()
-            .map(FunctionArgument::try_from)
-            .collect();
-
-        let ret = Self {
-            name: proto.name,
-            description: proto.description,
-            owner: proto.owner.into(),
-            executor_type,
-            payload: proto.payload,
-            public: proto.public,
-            arguments: arguments?,
-            inputs: inputs?,
-            outputs: outputs?,
-            user_allowlist: proto.user_allowlist,
-        };
-
-        Ok(ret)
-    }
-}
-
-impl From<GetFunctionResponse> for proto::GetFunctionResponse {
-    fn from(response: GetFunctionResponse) -> Self {
-        let inputs: Vec<proto::FunctionInput> = response
-            .inputs
-            .into_iter()
-            .map(proto::FunctionInput::from)
-            .collect();
-        let outputs: Vec<proto::FunctionOutput> = response
-            .outputs
-            .into_iter()
-            .map(proto::FunctionOutput::from)
-            .collect();
-        let arguments: Vec<proto::FunctionArgument> = response
-            .arguments
-            .into_iter()
-            .map(proto::FunctionArgument::from)
-            .collect();
-
-        Self {
-            name: response.name,
-            description: response.description,
-            owner: response.owner.into(),
-            executor_type: response.executor_type.into(),
-            payload: response.payload,
-            public: response.public,
-            arguments,
-            inputs,
-            outputs,
-            user_allowlist: response.user_allowlist,
-        }
-    }
-}
-
 impl std::convert::TryFrom<proto::FunctionArgument> for FunctionArgument {
     type Error = Error;
 
@@ -1577,14 +615,14 @@
     }
 }
 
-fn from_proto_ownership(proto: Vec<proto::OwnerList>) -> TaskFileOwners {
+pub fn from_proto_ownership(proto: Vec<proto::OwnerList>) -> TaskFileOwners {
     proto
         .into_iter()
         .map(|ol| (ol.data_name, ol.uids))
         .collect()
 }
 
-fn to_proto_ownership(ownership: TaskFileOwners) -> Vec<proto::OwnerList> {
+pub fn to_proto_ownership(ownership: TaskFileOwners) -> Vec<proto::OwnerList> {
     ownership
         .into_iter()
         .map(|(name, ol)| proto::OwnerList {
@@ -1594,63 +632,7 @@
         .collect()
 }
 
-impl std::convert::TryFrom<proto::CreateTaskRequest> for CreateTaskRequest {
-    type Error = Error;
-
-    fn try_from(proto: proto::CreateTaskRequest) -> Result<Self> {
-        let function_arguments: FunctionArguments = proto.function_arguments.try_into()?;
-        let inputs_ownership = from_proto_ownership(proto.inputs_ownership);
-        let outputs_ownership = from_proto_ownership(proto.outputs_ownership);
-        let function_id = proto.function_id.try_into()?;
-        let executor = proto.executor.try_into()?;
-
-        let ret = Self {
-            function_id,
-            function_arguments,
-            executor,
-            inputs_ownership,
-            outputs_ownership,
-        };
-        Ok(ret)
-    }
-}
-
-impl From<CreateTaskRequest> for proto::CreateTaskRequest {
-    fn from(request: CreateTaskRequest) -> Self {
-        let function_arguments = request.function_arguments.into_string();
-        let inputs_ownership = to_proto_ownership(request.inputs_ownership);
-        let outputs_ownership = to_proto_ownership(request.outputs_ownership);
-
-        Self {
-            function_id: request.function_id.to_string(),
-            function_arguments,
-            executor: request.executor.to_string(),
-            inputs_ownership,
-            outputs_ownership,
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::CreateTaskResponse> for CreateTaskResponse {
-    type Error = Error;
-
-    fn try_from(proto: proto::CreateTaskResponse) -> Result<Self> {
-        let task_id = proto.task_id.try_into()?;
-        let ret = Self { task_id };
-
-        Ok(ret)
-    }
-}
-
-impl From<CreateTaskResponse> for proto::CreateTaskResponse {
-    fn from(response: CreateTaskResponse) -> Self {
-        Self {
-            task_id: response.task_id.to_string(),
-        }
-    }
-}
-
-fn to_proto_file_ids(map: HashMap<String, ExternalID>) -> Vec<proto::DataMap> {
+pub fn to_proto_file_ids(map: HashMap<String, ExternalID>) -> Vec<proto::DataMap> {
     map.into_iter()
         .map(|(name, ext_id)| proto::DataMap {
             data_name: name,
@@ -1659,7 +641,7 @@
         .collect()
 }
 
-fn from_proto_file_ids(vector: Vec<proto::DataMap>) -> Result<HashMap<String, ExternalID>> {
+pub fn from_proto_file_ids(vector: Vec<proto::DataMap>) -> Result<HashMap<String, ExternalID>> {
     vector
         .into_iter()
         .map(|item| {
@@ -1670,224 +652,3 @@
         })
         .collect()
 }
-
-impl std::convert::TryFrom<proto::GetTaskRequest> for GetTaskRequest {
-    type Error = Error;
-
-    fn try_from(proto: proto::GetTaskRequest) -> Result<Self> {
-        let task_id = proto.task_id.try_into()?;
-        let ret = Self { task_id };
-
-        Ok(ret)
-    }
-}
-
-impl From<GetTaskRequest> for proto::GetTaskRequest {
-    fn from(request: GetTaskRequest) -> Self {
-        Self {
-            task_id: request.task_id.to_string(),
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::GetTaskResponse> for GetTaskResponse {
-    type Error = Error;
-
-    fn try_from(proto: proto::GetTaskResponse) -> Result<Self> {
-        let function_arguments: FunctionArguments = proto.function_arguments.try_into()?;
-        let inputs_ownership = from_proto_ownership(proto.inputs_ownership);
-        let outputs_ownership = from_proto_ownership(proto.outputs_ownership);
-        let assigned_inputs = from_proto_file_ids(proto.assigned_inputs)?;
-        let assigned_outputs = from_proto_file_ids(proto.assigned_outputs)?;
-        let status = i32_to_task_status(proto.status)?;
-        let function_id = proto.function_id.try_into()?;
-        let task_id = proto.task_id.try_into()?;
-        let result = proto.result.try_into()?;
-
-        let ret = Self {
-            task_id,
-            creator: proto.creator.into(),
-            function_id,
-            function_owner: proto.function_owner.into(),
-            function_arguments,
-            inputs_ownership,
-            outputs_ownership,
-            participants: UserList::new(proto.participants),
-            approved_users: UserList::new(proto.approved_users),
-            assigned_inputs,
-            assigned_outputs,
-            status,
-            result,
-        };
-
-        Ok(ret)
-    }
-}
-
-impl From<GetTaskResponse> for proto::GetTaskResponse {
-    fn from(response: GetTaskResponse) -> Self {
-        let function_arguments = response.function_arguments.into_string();
-        let inputs_ownership = to_proto_ownership(response.inputs_ownership);
-        let outputs_ownership = to_proto_ownership(response.outputs_ownership);
-        let assigned_inputs = to_proto_file_ids(response.assigned_inputs);
-        let assigned_outputs = to_proto_file_ids(response.assigned_outputs);
-        let status = i32_from_task_status(response.status);
-        Self {
-            task_id: response.task_id.to_string(),
-            creator: response.creator.to_string(),
-            function_id: response.function_id.to_string(),
-            function_owner: response.function_owner.to_string(),
-            function_arguments,
-            inputs_ownership,
-            outputs_ownership,
-            participants: response.participants.into(),
-            approved_users: response.approved_users.into(),
-            assigned_inputs,
-            assigned_outputs,
-            status,
-            result: Some(response.result.into()),
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::AssignDataRequest> for AssignDataRequest {
-    type Error = Error;
-
-    fn try_from(proto: proto::AssignDataRequest) -> Result<Self> {
-        let inputs = from_proto_file_ids(proto.inputs)?;
-        let outputs = from_proto_file_ids(proto.outputs)?;
-        let task_id = proto.task_id.try_into()?;
-        let ret = Self {
-            task_id,
-            inputs,
-            outputs,
-        };
-
-        Ok(ret)
-    }
-}
-
-impl From<AssignDataRequest> for proto::AssignDataRequest {
-    fn from(request: AssignDataRequest) -> Self {
-        let inputs = to_proto_file_ids(request.inputs);
-        let outputs = to_proto_file_ids(request.outputs);
-        Self {
-            task_id: request.task_id.to_string(),
-            inputs,
-            outputs,
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::AssignDataResponse> for AssignDataResponse {
-    type Error = Error;
-
-    fn try_from(_proto: proto::AssignDataResponse) -> Result<Self> {
-        Ok(AssignDataResponse)
-    }
-}
-
-impl From<AssignDataResponse> for proto::AssignDataResponse {
-    fn from(_response: AssignDataResponse) -> Self {
-        Self {}
-    }
-}
-
-impl std::convert::TryFrom<proto::ApproveTaskRequest> for ApproveTaskRequest {
-    type Error = Error;
-
-    fn try_from(proto: proto::ApproveTaskRequest) -> Result<Self> {
-        let task_id = proto.task_id.try_into()?;
-        let ret = Self { task_id };
-
-        Ok(ret)
-    }
-}
-
-impl From<ApproveTaskRequest> for proto::ApproveTaskRequest {
-    fn from(request: ApproveTaskRequest) -> Self {
-        Self {
-            task_id: request.task_id.to_string(),
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::ApproveTaskResponse> for ApproveTaskResponse {
-    type Error = Error;
-
-    fn try_from(_proto: proto::ApproveTaskResponse) -> Result<Self> {
-        Ok(ApproveTaskResponse)
-    }
-}
-
-impl From<ApproveTaskResponse> for proto::ApproveTaskResponse {
-    fn from(_response: ApproveTaskResponse) -> Self {
-        Self {}
-    }
-}
-
-impl std::convert::TryFrom<proto::InvokeTaskRequest> for InvokeTaskRequest {
-    type Error = Error;
-
-    fn try_from(proto: proto::InvokeTaskRequest) -> Result<Self> {
-        let task_id = proto.task_id.try_into()?;
-        let ret = Self { task_id };
-
-        Ok(ret)
-    }
-}
-
-impl From<InvokeTaskRequest> for proto::InvokeTaskRequest {
-    fn from(request: InvokeTaskRequest) -> Self {
-        Self {
-            task_id: request.task_id.to_string(),
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::InvokeTaskResponse> for InvokeTaskResponse {
-    type Error = Error;
-
-    fn try_from(_proto: proto::InvokeTaskResponse) -> Result<Self> {
-        Ok(InvokeTaskResponse)
-    }
-}
-
-impl From<InvokeTaskResponse> for proto::InvokeTaskResponse {
-    fn from(_response: InvokeTaskResponse) -> Self {
-        Self {}
-    }
-}
-
-impl std::convert::TryFrom<proto::CancelTaskRequest> for CancelTaskRequest {
-    type Error = Error;
-
-    fn try_from(proto: proto::CancelTaskRequest) -> Result<Self> {
-        let task_id = proto.task_id.try_into()?;
-        let ret = Self { task_id };
-
-        Ok(ret)
-    }
-}
-
-impl From<CancelTaskRequest> for proto::CancelTaskRequest {
-    fn from(request: CancelTaskRequest) -> Self {
-        Self {
-            task_id: request.task_id.to_string(),
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::CancelTaskResponse> for CancelTaskResponse {
-    type Error = Error;
-
-    fn try_from(_proto: proto::CancelTaskResponse) -> Result<Self> {
-        Ok(CancelTaskResponse)
-    }
-}
-
-impl From<CancelTaskResponse> for proto::CancelTaskResponse {
-    fn from(_response: CancelTaskResponse) -> Self {
-        Self {}
-    }
-}
diff --git a/services/proto/src/teaclave_management_service.rs b/services/proto/src/teaclave_management_service.rs
index e9612ea..2339e40 100644
--- a/services/proto/src/teaclave_management_service.rs
+++ b/services/proto/src/teaclave_management_service.rs
@@ -17,10 +17,9 @@
 
 use crate::teaclave_management_service_proto as proto;
 
-pub use proto::TeaclaveManagement;
-pub use proto::TeaclaveManagementClient;
-pub use proto::TeaclaveManagementRequest;
-pub use proto::TeaclaveManagementResponse;
+pub use proto::teaclave_management_client::TeaclaveManagementClient;
+pub use proto::teaclave_management_server::TeaclaveManagement;
+pub use proto::teaclave_management_server::TeaclaveManagementServer;
 
 pub type RegisterInputFileRequest = crate::teaclave_frontend_service::RegisterInputFileRequest;
 pub type UpdateInputFileRequest = crate::teaclave_frontend_service::UpdateInputFileRequest;
diff --git a/services/proto/src/teaclave_scheduler_service.rs b/services/proto/src/teaclave_scheduler_service.rs
index 3415b8e..abaca66 100644
--- a/services/proto/src/teaclave_scheduler_service.rs
+++ b/services/proto/src/teaclave_scheduler_service.rs
@@ -15,83 +15,49 @@
 // specific language governing permissions and limitations
 // under the License.
 
-#![allow(unused_imports)]
-#![allow(unused_variables)]
-
-use std::collections::HashMap;
-
-use crate::teaclave_common::{
-    i32_from_task_status, i32_to_task_status, ExecutorCommand, ExecutorStatus,
-};
+use crate::teaclave_common::{i32_from_task_status, ExecutorCommand, ExecutorStatus};
 use crate::teaclave_scheduler_service_proto as proto;
-use anyhow::{Error, Result};
-use core::convert::TryInto;
-pub use proto::TeaclaveScheduler;
-pub use proto::TeaclaveSchedulerClient;
-pub use proto::TeaclaveSchedulerRequest;
-pub use proto::TeaclaveSchedulerResponse;
-use teaclave_rpc::into_request;
+use anyhow::Result;
+pub use proto::teaclave_scheduler_client::TeaclaveSchedulerClient;
+pub use proto::teaclave_scheduler_server::TeaclaveScheduler;
+pub use proto::teaclave_scheduler_server::TeaclaveSchedulerServer;
+pub use proto::{
+    HeartbeatRequest, PublishTaskRequest, PullTaskRequest, UpdateTaskResultRequest,
+    UpdateTaskStatusRequest,
+};
+pub use proto::{
+    HeartbeatResponse, PublishTaskResponse, PullTaskResponse, SubscribeRequest, SubscribeResponse,
+    UpdateTaskResultResponse, UpdateTaskStatusResponse,
+};
+use teaclave_types::Storable;
 use teaclave_types::{StagedTask, TaskFailure, TaskOutputs, TaskResult, TaskStatus};
 use uuid::Uuid;
 
-#[into_request(TeaclaveSchedulerRequest::Subscribe)]
-pub struct SubscribeRequest {}
-
-#[into_request(TeaclaveSchedulerResponse::Subscribe)]
-pub struct SubscribeResponse {
-    pub success: bool,
-}
-
-#[into_request(TeaclaveSchedulerRequest::PullTask)]
-pub struct PullTaskRequest {
-    pub executor_id: Uuid,
-}
-
-#[into_request(TeaclaveSchedulerResponse::PullTask)]
-#[derive(Debug)]
-pub struct PullTaskResponse {
-    pub staged_task: StagedTask,
-}
-
-#[into_request(TeaclaveSchedulerRequest::Heartbeat)]
-pub struct HeartbeatRequest {
-    pub executor_id: Uuid,
-    pub status: ExecutorStatus,
-}
-
 impl HeartbeatRequest {
     pub fn new(executor_id: Uuid, status: ExecutorStatus) -> Self {
         Self {
-            executor_id,
-            status,
+            executor_id: executor_id.to_string(),
+            status: status.into(),
         }
     }
 }
 
-#[into_request(TeaclaveSchedulerResponse::Heartbeat)]
-#[derive(Debug)]
-pub struct HeartbeatResponse {
-    pub command: ExecutorCommand,
-}
-
 impl HeartbeatResponse {
     pub fn new(command: ExecutorCommand) -> Self {
-        Self { command }
+        Self {
+            command: command.into(),
+        }
     }
 }
 
 impl PullTaskResponse {
     pub fn new(staged_task: StagedTask) -> Self {
-        Self { staged_task }
+        Self {
+            staged_task: staged_task.to_vec().unwrap(),
+        }
     }
 }
 
-#[into_request(TeaclaveSchedulerRequest::UpdateTaskResult)]
-pub struct UpdateTaskResultRequest {
-    pub task_id: Uuid,
-    pub task_result: TaskResult,
-}
-
 impl UpdateTaskResultRequest {
     pub fn new(task_id: Uuid, task_result: Result<TaskOutputs>) -> Self {
         let result = match task_result {
@@ -101,243 +67,18 @@
             }),
         };
         Self {
-            task_id,
-            task_result: result,
+            task_id: task_id.to_string(),
+            result: Some(result.into()),
         }
     }
 }
 
-#[into_request(TeaclaveSchedulerResponse::UpdateTaskResult)]
-pub struct UpdateTaskResultResponse {}
-
-#[into_request(TeaclaveSchedulerRequest::UpdateTaskStatus)]
-pub struct UpdateTaskStatusRequest {
-    pub task_id: Uuid,
-    pub task_status: TaskStatus,
-}
-
 impl UpdateTaskStatusRequest {
     pub fn new(task_id: Uuid, task_status: TaskStatus) -> Self {
+        let task_status = i32_from_task_status(task_status);
         Self {
-            task_id,
+            task_id: task_id.to_string(),
             task_status,
         }
     }
 }
-#[into_request(TeaclaveSchedulerResponse::UpdateTaskStatus)]
-pub struct UpdateTaskStatusResponse {}
-
-#[into_request(TeaclaveSchedulerRequest::PublishTask)]
-pub struct PublishTaskRequest {
-    pub staged_task: StagedTask,
-}
-
-#[into_request(TeaclaveSchedulerResponse::PublishTask)]
-pub struct PublishTaskResponse {}
-
-impl std::convert::TryFrom<proto::SubscribeRequest> for SubscribeRequest {
-    type Error = Error;
-    fn try_from(proto: proto::SubscribeRequest) -> Result<Self> {
-        let ret = Self {};
-        Ok(ret)
-    }
-}
-
-impl std::convert::From<SubscribeRequest> for proto::SubscribeRequest {
-    fn from(req: SubscribeRequest) -> Self {
-        proto::SubscribeRequest {}
-    }
-}
-
-impl std::convert::TryFrom<proto::SubscribeResponse> for SubscribeResponse {
-    type Error = Error;
-    fn try_from(proto: proto::SubscribeResponse) -> Result<Self> {
-        let ret = Self {
-            success: proto.success,
-        };
-        Ok(ret)
-    }
-}
-
-impl std::convert::From<SubscribeResponse> for proto::SubscribeResponse {
-    fn from(req: SubscribeResponse) -> Self {
-        proto::SubscribeResponse {
-            success: req.success,
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::PullTaskRequest> for PullTaskRequest {
-    type Error = Error;
-    fn try_from(proto: proto::PullTaskRequest) -> Result<Self> {
-        let executor_id = Uuid::parse_str(&proto.executor_id)?;
-        let ret = Self { executor_id };
-        Ok(ret)
-    }
-}
-
-impl std::convert::From<PullTaskRequest> for proto::PullTaskRequest {
-    fn from(req: PullTaskRequest) -> Self {
-        let executor_id = req.executor_id.to_string();
-        proto::PullTaskRequest { executor_id }
-    }
-}
-
-impl std::convert::TryFrom<proto::PullTaskResponse> for PullTaskResponse {
-    type Error = Error;
-    fn try_from(proto: proto::PullTaskResponse) -> Result<Self> {
-        let staged_task = StagedTask::from_slice(&proto.staged_task)?;
-        let ret = Self { staged_task };
-        Ok(ret)
-    }
-}
-
-impl std::convert::From<PullTaskResponse> for proto::PullTaskResponse {
-    fn from(req: PullTaskResponse) -> Self {
-        proto::PullTaskResponse {
-            staged_task: req.staged_task.to_vec().unwrap(),
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::HeartbeatRequest> for HeartbeatRequest {
-    type Error = Error;
-    fn try_from(proto: proto::HeartbeatRequest) -> Result<Self> {
-        let executor_id = Uuid::parse_str(&proto.executor_id)?;
-        let status = proto.status.try_into()?;
-        let ret = Self {
-            executor_id,
-            status,
-        };
-        Ok(ret)
-    }
-}
-
-impl std::convert::From<HeartbeatRequest> for proto::HeartbeatRequest {
-    fn from(req: HeartbeatRequest) -> Self {
-        let executor_id = req.executor_id.to_string();
-        proto::HeartbeatRequest {
-            executor_id,
-            status: req.status.into(),
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::HeartbeatResponse> for HeartbeatResponse {
-    type Error = Error;
-    fn try_from(proto: proto::HeartbeatResponse) -> Result<Self> {
-        let command = proto.command.try_into()?;
-        let ret = Self { command };
-        Ok(ret)
-    }
-}
-
-impl std::convert::From<HeartbeatResponse> for proto::HeartbeatResponse {
-    fn from(req: HeartbeatResponse) -> Self {
-        proto::HeartbeatResponse {
-            command: req.command.into(),
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::UpdateTaskResultRequest> for UpdateTaskResultRequest {
-    type Error = Error;
-    fn try_from(proto: proto::UpdateTaskResultRequest) -> Result<Self> {
-        let ret = Self {
-            task_id: Uuid::parse_str(&proto.task_id)?,
-            task_result: proto.result.try_into()?,
-        };
-        Ok(ret)
-    }
-}
-
-impl std::convert::From<UpdateTaskResultRequest> for proto::UpdateTaskResultRequest {
-    fn from(req: UpdateTaskResultRequest) -> Self {
-        proto::UpdateTaskResultRequest {
-            task_id: req.task_id.to_string(),
-            result: Some(req.task_result.into()),
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::UpdateTaskResultResponse> for UpdateTaskResultResponse {
-    type Error = Error;
-    fn try_from(proto: proto::UpdateTaskResultResponse) -> Result<Self> {
-        let ret = Self {};
-        Ok(ret)
-    }
-}
-
-impl std::convert::From<UpdateTaskResultResponse> for proto::UpdateTaskResultResponse {
-    fn from(req: UpdateTaskResultResponse) -> Self {
-        proto::UpdateTaskResultResponse {}
-    }
-}
-
-impl std::convert::TryFrom<proto::UpdateTaskStatusRequest> for UpdateTaskStatusRequest {
-    type Error = Error;
-    fn try_from(proto: proto::UpdateTaskStatusRequest) -> Result<Self> {
-        let task_status = i32_to_task_status(proto.task_status)?;
-        let ret = Self {
-            task_id: Uuid::parse_str(&proto.task_id)?,
-            task_status,
-        };
-        Ok(ret)
-    }
-}
-
-impl std::convert::From<UpdateTaskStatusRequest> for proto::UpdateTaskStatusRequest {
-    fn from(req: UpdateTaskStatusRequest) -> Self {
-        let task_status = i32_from_task_status(req.task_status);
-        proto::UpdateTaskStatusRequest {
-            task_id: req.task_id.to_string(),
-            task_status,
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::UpdateTaskStatusResponse> for UpdateTaskStatusResponse {
-    type Error = Error;
-    fn try_from(proto: proto::UpdateTaskStatusResponse) -> Result<Self> {
-        let ret = Self {};
-        Ok(ret)
-    }
-}
-
-impl std::convert::From<UpdateTaskStatusResponse> for proto::UpdateTaskStatusResponse {
-    fn from(req: UpdateTaskStatusResponse) -> Self {
-        proto::UpdateTaskStatusResponse {}
-    }
-}
-
-use teaclave_types::Storable;
-impl std::convert::TryFrom<proto::PublishTaskRequest> for PublishTaskRequest {
-    type Error = Error;
-    fn try_from(proto: proto::PublishTaskRequest) -> Result<Self> {
-        let staged_task = StagedTask::from_slice(&proto.staged_task)?;
-        let ret = Self { staged_task };
-        Ok(ret)
-    }
-}
-
-impl std::convert::From<PublishTaskRequest> for proto::PublishTaskRequest {
-    fn from(req: PublishTaskRequest) -> Self {
-        proto::PublishTaskRequest {
-            staged_task: req.staged_task.to_vec().unwrap(),
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::PublishTaskResponse> for PublishTaskResponse {
-    type Error = Error;
-    fn try_from(proto: proto::PublishTaskResponse) -> Result<Self> {
-        let ret = Self {};
-        Ok(ret)
-    }
-}
-
-impl std::convert::From<PublishTaskResponse> for proto::PublishTaskResponse {
-    fn from(req: PublishTaskResponse) -> Self {
-        proto::PublishTaskResponse {}
-    }
-}
diff --git a/services/proto/src/teaclave_storage_service.rs b/services/proto/src/teaclave_storage_service.rs
index bb96033..d65f6c5 100644
--- a/services/proto/src/teaclave_storage_service.rs
+++ b/services/proto/src/teaclave_storage_service.rs
@@ -15,20 +15,15 @@
 // specific language governing permissions and limitations
 // under the License.
 
-use anyhow::{Error, Result};
-
 use crate::teaclave_storage_service_proto as proto;
-pub use proto::TeaclaveStorage;
-pub use proto::TeaclaveStorageClient;
-pub use proto::TeaclaveStorageRequest;
-pub use proto::TeaclaveStorageResponse;
-use teaclave_rpc::into_request;
-
-#[into_request(TeaclaveStorageRequest::Get)]
-#[derive(Debug)]
-pub struct GetRequest {
-    pub key: Vec<u8>,
-}
+pub use proto::teaclave_storage_client::TeaclaveStorageClient;
+pub use proto::teaclave_storage_server::TeaclaveStorage;
+pub use proto::teaclave_storage_server::TeaclaveStorageServer;
+pub use proto::{
+    DeleteRequest, DeleteResponse, DequeueRequest, DequeueResponse, EnqueueRequest,
+    EnqueueResponse, GetKeysByPrefixRequest, GetKeysByPrefixResponse, GetRequest, GetResponse,
+    PutRequest, PutResponse,
+};
 
 impl GetRequest {
     pub fn new(key: impl Into<Vec<u8>>) -> Self {
@@ -36,12 +31,6 @@
     }
 }
 
-#[into_request(TeaclaveStorageResponse::Get)]
-#[derive(Debug)]
-pub struct GetResponse {
-    pub value: Vec<u8>,
-}
-
 impl GetResponse {
     pub fn new(value: impl Into<Vec<u8>>) -> Self {
         Self {
@@ -50,13 +39,6 @@
     }
 }
 
-#[into_request(TeaclaveStorageRequest::Put)]
-#[derive(Debug)]
-pub struct PutRequest {
-    pub key: Vec<u8>,
-    pub value: Vec<u8>,
-}
-
 impl PutRequest {
     pub fn new(key: impl Into<Vec<u8>>, value: impl Into<Vec<u8>>) -> Self {
         Self {
@@ -66,33 +48,12 @@
     }
 }
 
-#[into_request(TeaclaveStorageResponse::Put)]
-#[derive(Debug, Default)]
-pub struct PutResponse;
-
-#[into_request(TeaclaveStorageRequest::Delete)]
-#[derive(Debug)]
-pub struct DeleteRequest {
-    pub key: Vec<u8>,
-}
-
 impl DeleteRequest {
     pub fn new(key: impl Into<Vec<u8>>) -> Self {
         Self { key: key.into() }
     }
 }
 
-#[into_request(TeaclaveStorageResponse::Delete)]
-#[derive(Debug, Default)]
-pub struct DeleteResponse;
-
-#[into_request(TeaclaveStorageRequest::Enqueue)]
-#[derive(Debug)]
-pub struct EnqueueRequest {
-    pub key: Vec<u8>,
-    pub value: Vec<u8>,
-}
-
 impl EnqueueRequest {
     pub fn new(key: impl Into<Vec<u8>>, value: impl Into<Vec<u8>>) -> Self {
         Self {
@@ -102,28 +63,12 @@
     }
 }
 
-#[into_request(TeaclaveStorageResponse::Enqueue)]
-#[derive(Debug, Default)]
-pub struct EnqueueResponse;
-
-#[into_request(TeaclaveStorageRequest::Dequeue)]
-#[derive(Debug)]
-pub struct DequeueRequest {
-    pub key: Vec<u8>,
-}
-
 impl DequeueRequest {
     pub fn new(key: impl Into<Vec<u8>>) -> Self {
         Self { key: key.into() }
     }
 }
 
-#[into_request(TeaclaveStorageResponse::Dequeue)]
-#[derive(Debug)]
-pub struct DequeueResponse {
-    pub value: Vec<u8>,
-}
-
 impl DequeueResponse {
     pub fn new(value: impl Into<Vec<u8>>) -> Self {
         Self {
@@ -132,12 +77,6 @@
     }
 }
 
-#[into_request(TeaclaveStorageRequest::GetKeysByPrefix)]
-#[derive(Debug)]
-pub struct GetKeysByPrefixRequest {
-    pub prefix: Vec<u8>,
-}
-
 impl GetKeysByPrefixRequest {
     pub fn new(prefix: impl Into<Vec<u8>>) -> Self {
         Self {
@@ -146,218 +85,31 @@
     }
 }
 
-#[into_request(TeaclaveStorageResponse::GetKeysByPrefix)]
-#[derive(Default, Debug)]
-pub struct GetKeysByPrefixResponse {
-    pub keys: Vec<Vec<u8>>,
-}
-
 impl GetKeysByPrefixResponse {
     pub fn new(keys: Vec<Vec<u8>>) -> Self {
         Self { keys }
     }
 }
 
-impl std::convert::TryFrom<proto::GetRequest> for GetRequest {
-    type Error = Error;
-
-    fn try_from(proto: proto::GetRequest) -> Result<Self> {
-        let ret = Self { key: proto.key };
-
-        Ok(ret)
-    }
+#[derive(Clone, serde::Serialize, serde::Deserialize, Debug)]
+#[serde(rename_all = "snake_case")]
+pub enum TeaclaveStorageRequest {
+    Get(GetRequest),
+    Put(PutRequest),
+    Delete(DeleteRequest),
+    Enqueue(EnqueueRequest),
+    Dequeue(DequeueRequest),
+    GetKeysByPrefix(GetKeysByPrefixRequest),
 }
 
-impl From<GetRequest> for proto::GetRequest {
-    fn from(request: GetRequest) -> Self {
-        Self { key: request.key }
-    }
-}
-
-impl std::convert::TryFrom<proto::GetResponse> for GetResponse {
-    type Error = Error;
-
-    fn try_from(proto: proto::GetResponse) -> Result<Self> {
-        let ret = Self { value: proto.value };
-
-        Ok(ret)
-    }
-}
-
-impl From<GetResponse> for proto::GetResponse {
-    fn from(response: GetResponse) -> Self {
-        Self {
-            value: response.value,
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::PutRequest> for PutRequest {
-    type Error = Error;
-
-    fn try_from(proto: proto::PutRequest) -> Result<Self> {
-        let ret = Self {
-            key: proto.key,
-            value: proto.value,
-        };
-
-        Ok(ret)
-    }
-}
-
-impl From<PutRequest> for proto::PutRequest {
-    fn from(request: PutRequest) -> Self {
-        Self {
-            key: request.key,
-            value: request.value,
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::PutResponse> for PutResponse {
-    type Error = Error;
-
-    fn try_from(_proto: proto::PutResponse) -> Result<Self> {
-        Ok(Self {})
-    }
-}
-
-impl From<PutResponse> for proto::PutResponse {
-    fn from(_response: PutResponse) -> Self {
-        Self {}
-    }
-}
-
-impl std::convert::TryFrom<proto::DeleteRequest> for DeleteRequest {
-    type Error = Error;
-
-    fn try_from(proto: proto::DeleteRequest) -> Result<Self> {
-        let ret = Self { key: proto.key };
-
-        Ok(ret)
-    }
-}
-
-impl From<DeleteRequest> for proto::DeleteRequest {
-    fn from(request: DeleteRequest) -> Self {
-        Self { key: request.key }
-    }
-}
-
-impl std::convert::TryFrom<proto::DeleteResponse> for DeleteResponse {
-    type Error = Error;
-
-    fn try_from(_proto: proto::DeleteResponse) -> Result<Self> {
-        Ok(Self {})
-    }
-}
-
-impl From<DeleteResponse> for proto::DeleteResponse {
-    fn from(_response: DeleteResponse) -> Self {
-        Self {}
-    }
-}
-
-impl std::convert::TryFrom<proto::EnqueueRequest> for EnqueueRequest {
-    type Error = Error;
-
-    fn try_from(proto: proto::EnqueueRequest) -> Result<Self> {
-        let ret = Self {
-            key: proto.key,
-            value: proto.value,
-        };
-
-        Ok(ret)
-    }
-}
-
-impl From<EnqueueRequest> for proto::EnqueueRequest {
-    fn from(request: EnqueueRequest) -> Self {
-        Self {
-            key: request.key,
-            value: request.value,
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::EnqueueResponse> for EnqueueResponse {
-    type Error = Error;
-
-    fn try_from(_proto: proto::EnqueueResponse) -> Result<Self> {
-        Ok(Self {})
-    }
-}
-
-impl From<EnqueueResponse> for proto::EnqueueResponse {
-    fn from(_response: EnqueueResponse) -> Self {
-        Self {}
-    }
-}
-
-impl std::convert::TryFrom<proto::DequeueRequest> for DequeueRequest {
-    type Error = Error;
-
-    fn try_from(proto: proto::DequeueRequest) -> Result<Self> {
-        let ret = Self { key: proto.key };
-
-        Ok(ret)
-    }
-}
-
-impl From<DequeueRequest> for proto::DequeueRequest {
-    fn from(request: DequeueRequest) -> Self {
-        Self { key: request.key }
-    }
-}
-
-impl std::convert::TryFrom<proto::DequeueResponse> for DequeueResponse {
-    type Error = Error;
-
-    fn try_from(proto: proto::DequeueResponse) -> Result<Self> {
-        Ok(Self { value: proto.value })
-    }
-}
-
-impl From<DequeueResponse> for proto::DequeueResponse {
-    fn from(response: DequeueResponse) -> Self {
-        Self {
-            value: response.value,
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::GetKeysByPrefixRequest> for GetKeysByPrefixRequest {
-    type Error = Error;
-
-    fn try_from(proto: proto::GetKeysByPrefixRequest) -> Result<Self> {
-        let ret = Self {
-            prefix: proto.prefix,
-        };
-
-        Ok(ret)
-    }
-}
-
-impl From<GetKeysByPrefixRequest> for proto::GetKeysByPrefixRequest {
-    fn from(request: GetKeysByPrefixRequest) -> Self {
-        Self {
-            prefix: request.prefix,
-        }
-    }
-}
-
-impl std::convert::TryFrom<proto::GetKeysByPrefixResponse> for GetKeysByPrefixResponse {
-    type Error = Error;
-
-    fn try_from(proto: proto::GetKeysByPrefixResponse) -> Result<Self> {
-        Ok(Self { keys: proto.keys })
-    }
-}
-
-impl From<GetKeysByPrefixResponse> for proto::GetKeysByPrefixResponse {
-    fn from(response: GetKeysByPrefixResponse) -> Self {
-        Self {
-            keys: response.keys,
-        }
-    }
+#[allow(clippy::large_enum_variant)]
+#[derive(Clone, serde::Serialize, serde::Deserialize, Debug)]
+#[serde(tag = "response", content = "content", rename_all = "snake_case")]
+pub enum TeaclaveStorageResponse {
+    Get(GetResponse),
+    Put(PutResponse),
+    Delete(DeleteResponse),
+    Enqueue(EnqueueResponse),
+    Dequeue(DequeueResponse),
+    GetKeysByPrefix(GetKeysByPrefixResponse),
 }
diff --git a/services/scheduler/enclave/Cargo.toml b/services/scheduler/enclave/Cargo.toml
index 3ac70ad..7c47ad1 100644
--- a/services/scheduler/enclave/Cargo.toml
+++ b/services/scheduler/enclave/Cargo.toml
@@ -48,6 +48,7 @@
 serde_json    = { version = "1.0.39" }
 serde         = { version = "1.0.92", features = ["derive"] }
 thiserror     = { version = "1.0.9" }
+tokio         = { version = "1.0", features = ["rt-multi-thread", "time", "macros"] }
 gbdt          = { version = "0.1.0", features = ["input", "enable_training"] }
 uuid          = { version = "0.8.1", features = ["v4"] }
 
diff --git a/services/scheduler/enclave/src/error.rs b/services/scheduler/enclave/src/error.rs
index 964d29b..555aea1 100644
--- a/services/scheduler/enclave/src/error.rs
+++ b/services/scheduler/enclave/src/error.rs
@@ -15,9 +15,8 @@
 // specific language governing permissions and limitations
 // under the License.
 
-use teaclave_types::TeaclaveServiceResponseError;
+use teaclave_rpc::{Code, Status};
 use thiserror::Error;
-
 #[derive(Error, Debug)]
 pub enum SchedulerServiceError {
     #[error("service internal error")]
@@ -30,9 +29,14 @@
     StorageError,
 }
 
-impl From<SchedulerServiceError> for TeaclaveServiceResponseError {
+impl From<SchedulerServiceError> for Status {
     fn from(error: SchedulerServiceError) -> Self {
         log::debug!("SchedulerServiceError: {:?}", error);
-        TeaclaveServiceResponseError::RequestError(error.to_string())
+        let msg = error.to_string();
+        let code = match error {
+            SchedulerServiceError::Service(_) => Code::Internal,
+            _ => Code::Unknown,
+        };
+        Status::new(code, msg)
     }
 }
diff --git a/services/scheduler/enclave/src/lib.rs b/services/scheduler/enclave/src/lib.rs
index 2b9c8c2..b201a3c 100644
--- a/services/scheduler/enclave/src/lib.rs
+++ b/services/scheduler/enclave/src/lib.rs
@@ -15,8 +15,8 @@
 // specific language governing permissions and limitations
 // under the License.
 
-use std::sync::{Arc, Mutex};
-
+use std::sync::Arc;
+use tokio::sync::Mutex;
 #[macro_use]
 extern crate log;
 extern crate sgx_types;
@@ -30,11 +30,7 @@
 use teaclave_binder::{handle_ecall, register_ecall_handler};
 use teaclave_config::build::{AS_ROOT_CA_CERT, AUDITOR_PUBLIC_KEYS, SCHEDULER_INBOUND_SERVICES};
 use teaclave_config::RuntimeConfig;
-use teaclave_proto::teaclave_scheduler_service::{
-    TeaclaveSchedulerRequest, TeaclaveSchedulerResponse,
-};
-use teaclave_rpc::config::SgxTrustedTlsServerConfig;
-use teaclave_rpc::server::SgxTrustedTlsServer;
+use teaclave_proto::teaclave_scheduler_service::TeaclaveSchedulerServer;
 use teaclave_service_enclave_utils::create_trusted_storage_endpoint;
 use teaclave_service_enclave_utils::ServiceEnclave;
 use teaclave_types::{EnclaveInfo, TeeServiceError, TeeServiceResult};
@@ -43,7 +39,10 @@
 mod publisher;
 mod service;
 
-fn start_service(config: &RuntimeConfig) -> Result<()> {
+// Sets the number of worker threads the Runtime will use.
+const N_WORKERS: usize = 8;
+
+async fn start_service(config: &RuntimeConfig) -> Result<()> {
     info!("Starting Scheduler...");
 
     let listen_address = config.internal_endpoints.scheduler.listen_address;
@@ -66,20 +65,17 @@
             None => Err(anyhow!("cannot get enclave attribute of {}", service)),
         })
         .collect::<Result<_>>()?;
-    let server_config =
-        SgxTrustedTlsServerConfig::from_attested_tls_config(attested_tls_config.clone())?
-            .attestation_report_verifier(
-                accepted_enclave_attrs,
-                AS_ROOT_CA_CERT,
-                verifier::universal_quote_verifier,
-            )?;
-    info!(" Starting Scheduler: Server config setup finished ...");
 
-    let mut server =
-        SgxTrustedTlsServer::<TeaclaveSchedulerResponse, TeaclaveSchedulerRequest>::new(
-            listen_address,
-            server_config,
-        );
+    let server_config = teaclave_rpc::config::SgxTrustedTlsServerConfig::from_attested_tls_config(
+        attested_tls_config.clone(),
+    )?
+    .attestation_report_verifier(
+        accepted_enclave_attrs,
+        AS_ROOT_CA_CERT,
+        verifier::universal_quote_verifier,
+    )?
+    .into();
+    info!(" Starting Scheduler: Server config setup finished ...");
 
     let storage_service_address = &config.internal_endpoints.storage.advertised_address;
     let storage_service_endpoint = create_trusted_storage_endpoint(
@@ -91,7 +87,8 @@
     )?;
     info!(" Starting Scheduler: setup storage endpoint finished ...");
 
-    let service_resources = service::TeaclaveSchedulerResources::new(storage_service_endpoint)?;
+    let service_resources =
+        service::TeaclaveSchedulerResources::new(storage_service_endpoint).await?;
 
     let service_resources = Arc::new(Mutex::new(service_resources));
 
@@ -100,18 +97,21 @@
     let deamon = service::TeaclaveSchedulerDeamon::new(&service_resources);
 
     let deamon_handle = std::thread::spawn(move || {
-        let _ = deamon.run();
+        let rt = tokio::runtime::Builder::new_current_thread()
+            .enable_all()
+            .build()
+            .unwrap();
+        let _ = rt.block_on(deamon.run());
     });
 
     info!(" Starting Scheduler: start listening ...");
 
-    match server.start(service) {
-        Ok(_) => (),
-        Err(e) => {
-            error!("Service exit, error: {}.", e);
-        }
-    }
-
+    teaclave_rpc::transport::Server::builder()
+        .tls_config(server_config)
+        .map_err(|_| anyhow::anyhow!("TeaclaveFrontendServer tls config error"))?
+        .add_service(TeaclaveSchedulerServer::new(service))
+        .serve(listen_address)
+        .await?;
     deamon_handle.join().unwrap();
 
     Ok(())
@@ -119,10 +119,17 @@
 
 #[handle_ecall]
 fn handle_start_service(input: &StartServiceInput) -> TeeServiceResult<StartServiceOutput> {
-    match start_service(&input.config) {
+    let result = tokio::runtime::Builder::new_multi_thread()
+        .worker_threads(N_WORKERS)
+        .enable_all()
+        .build()
+        .map_err(|_| TeeServiceError::SgxError)?
+        .block_on(start_service(&input.config));
+
+    match result {
         Ok(_) => Ok(StartServiceOutput),
         Err(e) => {
-            log::error!("Failed to start the service: {}", e);
+            error!("Failed to run service: {}", e);
             Err(TeeServiceError::ServiceError)
         }
     }
diff --git a/services/scheduler/enclave/src/publisher.rs b/services/scheduler/enclave/src/publisher.rs
index 97c9a17..c4d3afe 100644
--- a/services/scheduler/enclave/src/publisher.rs
+++ b/services/scheduler/enclave/src/publisher.rs
@@ -25,57 +25,31 @@
 use std::thread;
 use std::time::Duration;
 
-use teaclave_proto::teaclave_scheduler_service::*;
-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::{
-    StagedTask, Storable, TeaclaveServiceResponseError, TeaclaveServiceResponseResult,
-};
-
 use anyhow::anyhow;
 use anyhow::Result;
+use teaclave_proto::teaclave_scheduler_service::*;
+use teaclave_proto::teaclave_storage_service::*;
+use teaclave_rpc::transport::{channel::Endpoint, Channel};
+use teaclave_rpc::Request;
+use teaclave_types::{StagedTask, Storable, TeaclaveServiceResponseResult};
 use thiserror::Error;
 
 #[derive(Clone)]
 pub(crate) struct PublisherService {
-    storage_client: Arc<Mutex<TeaclaveStorageClient>>,
-    scheduler_client: Arc<Mutex<TeaclaveSchedulerClient>>,
+    storage_client: Arc<Mutex<TeaclaveStorageClient<Channel>>>,
+    scheduler_client: Arc<Mutex<TeaclaveSchedulerClient<Channel>>>,
 }
 
 impl PublisherService {
-    pub(crate) fn new(
+    pub(crate) async fn new(
         storage_service_endpoint: Endpoint,
         scheduler_service_endpoint: Endpoint,
     ) -> Result<Self> {
-        let mut i = 0;
-        let channel = loop {
-            match storage_service_endpoint.connect() {
-                Ok(channel) => break channel,
-                Err(_) => {
-                    anyhow::ensure!(i < 10, "failed to connect to storage service");
-                    log::debug!("Failed to connect to storage service, retry {}", i);
-                    i += 1;
-                }
-            }
-            std::thread::sleep(std::time::Duration::from_secs(3));
-        };
-        let storage_client = Arc::new(Mutex::new(TeaclaveStorageClient::new(channel)?));
+        let channel = storage_service_endpoint.connect().await?;
+        let storage_client = Arc::new(Mutex::new(TeaclaveStorageClient::new(channel)));
+        let channel = scheduler_service_endpoint.connect().await?;
 
-        let mut i = 0;
-        let channel = loop {
-            match scheduler_service_endpoint.connect() {
-                Ok(channel) => break channel,
-                Err(_) => {
-                    anyhow::ensure!(i < 10, "failed to connect to storage service");
-                    log::debug!("Failed to connect to storage service, retry {}", i);
-                    i += 1;
-                }
-            }
-            std::thread::sleep(std::time::Duration::from_secs(1));
-        };
-        let scheduler_client = Arc::new(Mutex::new(TeaclaveSchedulerClient::new(channel)?));
+        let scheduler_client = Arc::new(Mutex::new(TeaclaveSchedulerClient::new(channel)));
 
         let service = Self {
             storage_client,
diff --git a/services/scheduler/enclave/src/service.rs b/services/scheduler/enclave/src/service.rs
index a9f0d16..e3be03b 100644
--- a/services/scheduler/enclave/src/service.rs
+++ b/services/scheduler/enclave/src/service.rs
@@ -19,17 +19,17 @@
 
 use std::collections::{HashMap, HashSet, VecDeque};
 use std::convert::TryInto;
-use std::sync::{Arc, Mutex};
+use std::sync::Arc;
 use std::time::{Duration, SystemTime};
 #[allow(unused_imports)]
 use std::untrusted::time::SystemTimeEx;
+use tokio::sync::Mutex;
 
 use teaclave_proto::teaclave_common::{ExecutorCommand, ExecutorStatus};
 use teaclave_proto::teaclave_scheduler_service::*;
 use teaclave_proto::teaclave_storage_service::*;
-use teaclave_rpc::endpoint::Endpoint;
-use teaclave_rpc::Request;
-use teaclave_service_enclave_utils::teaclave_service;
+use teaclave_rpc::transport::{channel::Endpoint, Channel};
+use teaclave_rpc::{Request, Response};
 use teaclave_types::*;
 use uuid::Uuid;
 
@@ -38,14 +38,13 @@
 
 const EXECUTOR_TIMEOUT_SECS: u64 = 30;
 
-#[teaclave_service(teaclave_scheduler_service, TeaclaveScheduler, TeaclaveSchedulerError)]
 #[derive(Clone)]
 pub(crate) struct TeaclaveSchedulerService {
     resources: Arc<Mutex<TeaclaveSchedulerResources>>,
 }
 
 pub struct TeaclaveSchedulerResources {
-    storage_client: Arc<Mutex<TeaclaveStorageClient>>,
+    storage_client: Arc<Mutex<TeaclaveStorageClient<Channel>>>,
     // map executor_id to task_id
     task_queue: VecDeque<StagedTask>,
     executors_tasks: HashMap<Uuid, Uuid>,
@@ -59,23 +58,20 @@
 }
 
 impl TeaclaveSchedulerDeamon {
-    pub fn run(&self) -> Result<()> {
+    pub async fn run(&self) -> Result<()> {
         loop {
             std::thread::sleep(std::time::Duration::from_secs(2));
 
-            let mut resources = self
-                .resources
-                .lock()
-                .map_err(|_| anyhow!("cannot lock scheduler resources"))?;
+            let mut resources = self.resources.lock().await;
 
             let key = StagedTask::get_queue_key().as_bytes();
 
             log::debug!("Pulling task/cancel queue");
-            while let Ok(canceled_task) = resources.pull_cancel_queue() {
+            while let Ok(canceled_task) = resources.pull_cancel_queue().await {
                 resources.tasks_to_cancel.insert(canceled_task.task_id);
             }
 
-            while let Ok(staged_task) = resources.pull_staged_task::<StagedTask>(key) {
+            while let Ok(staged_task) = resources.pull_staged_task::<StagedTask>(key).await {
                 log::debug!("deamon: Pulled staged task: {:?}", staged_task);
                 resources.task_queue.push_back(staged_task);
             }
@@ -99,7 +95,7 @@
                 resources.executors_status.remove(&executor_id);
                 if let Some(task_id) = resources.executors_tasks.remove(&executor_id) {
                     // report task faliure
-                    let ts = resources.get_task_state(&task_id)?;
+                    let ts = resources.get_task_state(&task_id).await?;
                     if ts.is_ended() {
                         continue;
                     }
@@ -117,7 +113,7 @@
                     task.update_result(result_err)?;
 
                     let ts = TaskState::from(task);
-                    resources.put_into_db(&ts)?;
+                    resources.put_into_db(&ts).await?;
                 }
             }
         }
@@ -141,20 +137,12 @@
 }
 
 impl TeaclaveSchedulerResources {
-    pub(crate) fn new(storage_service_endpoint: Endpoint) -> Result<Self> {
-        let mut i = 0;
-        let channel = loop {
-            match storage_service_endpoint.connect() {
-                Ok(channel) => break channel,
-                Err(_) => {
-                    anyhow::ensure!(i < 10, "failed to connect to storage service");
-                    log::warn!("Failed to connect to storage service, retry {}", i);
-                    i += 1;
-                }
-            }
-            std::thread::sleep(std::time::Duration::from_secs(3));
-        };
-        let storage_client = Arc::new(Mutex::new(TeaclaveStorageClient::new(channel)?));
+    pub(crate) async fn new(storage_service_endpoint: Endpoint) -> Result<Self> {
+        let channel = storage_service_endpoint
+            .connect()
+            .await
+            .map_err(|e| anyhow!("Failed to connect to storage service.{:?}", e))?;
+        let storage_client = Arc::new(Mutex::new(TeaclaveStorageClient::new(channel)));
         let task_queue = VecDeque::new();
         let executors_tasks = HashMap::new();
         let executors_status = HashMap::new();
@@ -173,7 +161,7 @@
         Ok(resources)
     }
 
-    fn pull_staged_task<T: Storable>(
+    async fn pull_staged_task<T: Storable>(
         &self,
         key: &[u8],
     ) -> std::result::Result<T, SchedulerServiceError> {
@@ -182,27 +170,31 @@
             .storage_client
             .clone()
             .lock()
-            .map_err(|_| anyhow!("cannot lock storage client"))?
+            .await
             .dequeue(dequeue_request)
-            .map_err(|_| SchedulerServiceError::StorageError)?;
+            .await
+            .map_err(|_| SchedulerServiceError::StorageError)?
+            .into_inner();
         T::from_slice(dequeue_response.value.as_slice()).map_err(SchedulerServiceError::Service)
     }
 
-    fn pull_cancel_queue(&self) -> std::result::Result<TaskState, SchedulerServiceError> {
+    async fn pull_cancel_queue(&self) -> std::result::Result<TaskState, SchedulerServiceError> {
         let dequeue_request = DequeueRequest::new(CANCEL_QUEUE_KEY.as_bytes());
         let dequeue_response = self
             .storage_client
             .clone()
             .lock()
-            .map_err(|_| anyhow!("cannot lock storage client"))?
+            .await
             .dequeue(dequeue_request)
-            .map_err(|_| SchedulerServiceError::StorageError)?;
+            .await
+            .map_err(|_| SchedulerServiceError::StorageError)?
+            .into_inner();
         TaskState::from_slice(dequeue_response.value.as_slice())
             .map_err(SchedulerServiceError::Service)
     }
 
-    fn cancel_task(&self, task_id: Uuid) -> std::result::Result<(), SchedulerServiceError> {
-        let ts = self.get_task_state(&task_id)?;
+    async fn cancel_task(&self, task_id: Uuid) -> std::result::Result<(), SchedulerServiceError> {
+        let ts = self.get_task_state(&task_id).await?;
         let mut task: Task<Cancel> = ts.try_into()?;
 
         // Only TaskStatus::Running/Staged is allowed here.
@@ -211,62 +203,57 @@
         task.update_result(result_err)?;
 
         let ts = TaskState::from(task);
-        self.put_into_db(&ts)?;
+        self.put_into_db(&ts).await?;
 
         Ok(())
     }
 
-    fn get_task_state(&self, task_id: &Uuid) -> Result<TaskState> {
+    async fn get_task_state(&self, task_id: &Uuid) -> Result<TaskState> {
         let key = ExternalID::new(TaskState::key_prefix(), task_id.to_owned());
-        self.get_from_db(&key)
+        self.get_from_db(&key).await
     }
 
-    fn get_from_db<T: Storable>(&self, key: &ExternalID) -> Result<T> {
+    async fn get_from_db<T: Storable>(&self, key: &ExternalID) -> Result<T> {
         anyhow::ensure!(T::match_prefix(&key.prefix), "Key prefix doesn't match.");
         let get_request = GetRequest::new(key.to_bytes());
-        let response = self
-            .storage_client
-            .clone()
-            .lock()
-            .map_err(|_| anyhow!("cannot lock storage client"))?
-            .get(get_request)?;
+        let storage = self.storage_client.clone();
+        let mut storage = storage.lock().await;
+
+        let response = storage.get(get_request).await?.into_inner();
         T::from_slice(response.value.as_slice())
     }
 
-    fn put_into_db(&self, item: &impl Storable) -> Result<()> {
+    async fn put_into_db(&self, item: &impl Storable) -> Result<()> {
         let k = item.key();
         let v = item.to_vec()?;
         let put_request = PutRequest::new(k.as_slice(), v.as_slice());
-        let _put_response = self
-            .storage_client
-            .clone()
-            .lock()
-            .map_err(|_| anyhow!("cannot lock storage client"))?
-            .put(put_request)?;
+        let cli = self.storage_client.clone();
+        let mut client = cli.lock().await;
+
+        let _put_response = client.put(put_request).await?;
         Ok(())
     }
 }
 
+#[teaclave_rpc::async_trait]
 impl TeaclaveScheduler for TeaclaveSchedulerService {
     // Publisher
-    fn publish_task(
+    async fn publish_task(
         &self,
         request: Request<PublishTaskRequest>,
     ) -> TeaclaveServiceResponseResult<PublishTaskResponse> {
         // XXX: Publisher is not implemented
 
-        let mut resources = self
-            .resources
-            .lock()
-            .map_err(|_| anyhow!("cannot lock scheduler resources"))?;
+        let mut resources = self.resources.lock().await;
 
-        let staged_task = request.message.staged_task;
+        let staged_task =
+            StagedTask::from_slice(&request.get_ref().staged_task).map_err(tonic_error)?;
         resources.task_queue.push_back(staged_task);
-        Ok(PublishTaskResponse {})
+        Ok(Response::new(PublishTaskResponse {}))
     }
 
     // Subscriber
-    fn subscribe(
+    async fn subscribe(
         &self,
         _request: Request<SubscribeRequest>,
     ) -> TeaclaveServiceResponseResult<SubscribeResponse> {
@@ -274,19 +261,16 @@
         unimplemented!()
     }
 
-    fn heartbeat(
+    async fn heartbeat(
         &self,
         request: Request<HeartbeatRequest>,
     ) -> TeaclaveServiceResponseResult<HeartbeatResponse> {
-        let mut resources = self
-            .resources
-            .lock()
-            .map_err(|_| anyhow!("cannot lock scheduler resources"))?;
+        let mut resources = self.resources.lock().await;
 
         let mut command = ExecutorCommand::NoAction;
 
-        let executor_id = request.message.executor_id;
-        let status = request.message.status;
+        let executor_id = Uuid::parse_str(&request.get_ref().executor_id).map_err(tonic_error)?;
+        let status = request.get_ref().status.try_into().map_err(tonic_error)?;
 
         resources.executors_status.insert(executor_id, status);
 
@@ -307,8 +291,8 @@
                             executor_id,
                             task_id
                         );
-                        resources.cancel_task(task_id)?;
-                        return Ok(HeartbeatResponse { command });
+                        resources.cancel_task(task_id).await.map_err(tonic_error)?;
+                        return Ok(Response::new(HeartbeatResponse::new(command)));
                     }
                 }
                 ExecutorStatus::Idle => {
@@ -321,84 +305,83 @@
             command = ExecutorCommand::NewTask;
         }
 
-        let response = HeartbeatResponse { command };
-        Ok(response)
+        let response = HeartbeatResponse::new(command);
+        Ok(Response::new(response))
     }
 
-    fn pull_task(
+    async fn pull_task(
         &self,
         request: Request<PullTaskRequest>,
     ) -> TeaclaveServiceResponseResult<PullTaskResponse> {
-        let request = request.message;
-        let mut resources = self
-            .resources
-            .lock()
-            .map_err(|_| anyhow!("cannot lock scheduler resources"))?;
-
+        let request = request.get_ref();
+        let mut resources = self.resources.lock().await;
         match resources.task_queue.pop_front() {
             Some(task) => match resources.tasks_to_cancel.take(&task.task_id) {
                 Some(task_id) => {
-                    resources.cancel_task(task_id)?;
+                    resources.cancel_task(task_id).await?;
                     Err(SchedulerServiceError::TaskCanceled.into())
                 }
                 None => {
-                    resources
-                        .executors_tasks
-                        .insert(request.executor_id, task.task_id);
-                    Ok(PullTaskResponse::new(task))
+                    resources.executors_tasks.insert(
+                        Uuid::parse_str(&request.executor_id).map_err(tonic_error)?,
+                        task.task_id,
+                    );
+                    Ok(Response::new(PullTaskResponse::new(task)))
                 }
             },
             None => Err(SchedulerServiceError::TaskQueueEmpty.into()),
         }
     }
 
-    fn update_task_status(
+    async fn update_task_status(
         &self,
         request: Request<UpdateTaskStatusRequest>,
     ) -> TeaclaveServiceResponseResult<UpdateTaskStatusResponse> {
-        let resources = self
-            .resources
-            .lock()
-            .map_err(|_| anyhow!("cannot lock scheduler resources"))?;
+        let resources = self.resources.lock().await;
 
-        let request = request.message;
-        let ts = resources.get_task_state(&request.task_id)?;
-        let task: Task<Run> = ts.try_into()?;
+        let task_id = Uuid::parse_str(&request.get_ref().task_id).map_err(tonic_error)?;
+        let ts = resources
+            .get_task_state(&task_id)
+            .await
+            .map_err(tonic_error)?;
+        let task: Task<Run> = ts.try_into().map_err(tonic_error)?;
 
         log::debug!("UpdateTaskStatus: Task {:?}", task);
         // Only TaskStatus::Running is implicitly allowed here.
 
         let ts = TaskState::from(task);
-        resources.put_into_db(&ts)?;
-        Ok(UpdateTaskStatusResponse {})
+        resources.put_into_db(&ts).await.map_err(tonic_error)?;
+        Ok(Response::new(UpdateTaskStatusResponse {}))
     }
 
-    fn update_task_result(
+    async fn update_task_result(
         &self,
         request: Request<UpdateTaskResultRequest>,
     ) -> TeaclaveServiceResponseResult<UpdateTaskResultResponse> {
-        let resources = self
-            .resources
-            .lock()
-            .map_err(|_| anyhow!("cannot lock scheduler resources"))?;
+        let resources = self.resources.lock().await;
 
-        let request = request.message;
-        let ts = resources.get_task_state(&request.task_id)?;
-        let mut task: Task<Finish> = ts.try_into()?;
-
-        if let TaskResult::Ok(outputs) = &request.task_result {
+        let request = request.into_inner();
+        let ts = resources
+            .get_task_state(&Uuid::parse_str(&request.task_id).map_err(tonic_error)?)
+            .await
+            .map_err(tonic_error)?;
+        let mut task: Task<Finish> = ts.try_into().map_err(tonic_error)?;
+        let task_result: TaskResult = request.result.try_into().map_err(tonic_error)?;
+        if let TaskResult::Ok(outputs) = task_result.clone() {
             for (key, auth_tag) in outputs.tags_map.iter() {
-                let outfile = task.update_output_cmac(key, auth_tag)?;
-                resources.put_into_db(outfile)?;
+                let outfile = task
+                    .update_output_cmac(key, auth_tag)
+                    .map_err(tonic_error)?;
+                resources.put_into_db(outfile).await.map_err(tonic_error)?;
             }
         };
 
         // Updating task result means we have finished execution
-        task.update_result(request.task_result)?;
+        task.update_result(task_result).map_err(tonic_error)?;
         log::debug!("UpdateTaskResult: Task {:?}", task);
 
         let ts = TaskState::from(task);
-        resources.put_into_db(&ts)?;
-        Ok(UpdateTaskResultResponse {})
+        resources.put_into_db(&ts).await.map_err(tonic_error)?;
+        Ok(Response::new(UpdateTaskResultResponse {}))
     }
 }
diff --git a/services/storage/enclave/Cargo.toml b/services/storage/enclave/Cargo.toml
index 1392114..ede23df 100644
--- a/services/storage/enclave/Cargo.toml
+++ b/services/storage/enclave/Cargo.toml
@@ -48,6 +48,7 @@
 log       = { version = "0.4.17", features = ["release_max_level_info"] }
 serde     = { version = "1.0.92" }
 thiserror = { version = "1.0.9" }
+tokio     = { version = "1.0", features = ["rt-multi-thread", "time", "macros"] }
 
 rusty-leveldb                  = { path = "../../../common/rusty_leveldb_sgx" }
 teaclave_attestation           = { path = "../../../attestation" }
diff --git a/services/storage/enclave/src/error.rs b/services/storage/enclave/src/error.rs
index 4f9dd8e..0605be5 100644
--- a/services/storage/enclave/src/error.rs
+++ b/services/storage/enclave/src/error.rs
@@ -15,7 +15,7 @@
 // specific language governing permissions and limitations
 // under the License.
 
-use teaclave_types::TeaclaveServiceResponseError;
+use teaclave_rpc::{Code, Status};
 use thiserror::Error;
 
 #[derive(Error, Debug)]
@@ -28,9 +28,14 @@
     Service(#[from] anyhow::Error),
 }
 
-impl From<StorageServiceError> for TeaclaveServiceResponseError {
+impl From<StorageServiceError> for teaclave_rpc::Status {
     fn from(error: StorageServiceError) -> Self {
         log::debug!("StorageServiceError: {:?}", error);
-        TeaclaveServiceResponseError::RequestError(error.to_string())
+        let msg = error.to_string();
+        let code = match error {
+            StorageServiceError::Service(_) => Code::Internal,
+            _ => Code::Unknown,
+        };
+        Status::new(code, msg)
     }
 }
diff --git a/services/storage/enclave/src/lib.rs b/services/storage/enclave/src/lib.rs
index dabe785..021f705 100644
--- a/services/storage/enclave/src/lib.rs
+++ b/services/storage/enclave/src/lib.rs
@@ -20,8 +20,8 @@
 extern crate sgx_types;
 
 use std::cell::RefCell;
-use std::sync::mpsc::channel;
 use std::thread;
+use tokio::sync::mpsc::unbounded_channel;
 
 use anyhow::{anyhow, Result};
 use rusty_leveldb::DB;
@@ -34,9 +34,8 @@
 use teaclave_binder::{handle_ecall, register_ecall_handler};
 use teaclave_config::build::{AS_ROOT_CA_CERT, AUDITOR_PUBLIC_KEYS, STORAGE_INBOUND_SERVICES};
 use teaclave_config::RuntimeConfig;
-use teaclave_proto::teaclave_storage_service::{TeaclaveStorageRequest, TeaclaveStorageResponse};
+use teaclave_proto::teaclave_storage_service::TeaclaveStorageServer;
 use teaclave_rpc::config::SgxTrustedTlsServerConfig;
-use teaclave_rpc::server::SgxTrustedTlsServer;
 use teaclave_service_enclave_utils::ServiceEnclave;
 use teaclave_types::{EnclaveInfo, TeeServiceError, TeeServiceResult};
 
@@ -44,7 +43,7 @@
 mod proxy;
 mod service;
 
-fn start_service(config: &RuntimeConfig) -> Result<()> {
+async fn start_service(config: &RuntimeConfig) -> Result<()> {
     info!("Starting Storage...");
 
     let listen_address = config.internal_endpoints.storage.listen_address;
@@ -67,16 +66,19 @@
             None => Err(anyhow!("cannot get enclave attribute of {}", service)),
         })
         .collect::<Result<_>>()?;
-    let server_config = SgxTrustedTlsServerConfig::from_attested_tls_config(attested_tls_config)?
-        .attestation_report_verifier(
-        accepted_enclave_attrs,
-        AS_ROOT_CA_CERT,
-        verifier::universal_quote_verifier,
-    )?;
+
+    let server_config =
+        SgxTrustedTlsServerConfig::from_attested_tls_config(attested_tls_config.clone())?
+            .attestation_report_verifier(
+                accepted_enclave_attrs,
+                AS_ROOT_CA_CERT,
+                verifier::universal_quote_verifier,
+            )?
+            .into();
     info!(" Starting Storage: Server config setup finished ...");
 
-    let (sender, receiver) = channel();
-    thread::spawn(move || {
+    let (sender, receiver) = unbounded_channel();
+    let storage_handle = thread::spawn(move || {
         info!(" Starting Storage: opening database ...");
         #[cfg(test_mode)]
         let db = test_mode::create_mock_db();
@@ -89,20 +91,17 @@
         storage_service.start();
     });
 
-    let mut server = SgxTrustedTlsServer::<TeaclaveStorageResponse, TeaclaveStorageRequest>::new(
-        listen_address,
-        server_config,
-    );
-
     let service = proxy::ProxyService::new(sender);
 
     info!(" Starting Storage: start listening ...");
-    match server.start(service) {
-        Ok(_) => (),
-        Err(e) => {
-            error!("Service exit, error: {}.", e);
-        }
-    }
+
+    teaclave_rpc::transport::Server::builder()
+        .tls_config(server_config)
+        .map_err(|_| anyhow::anyhow!("TeaclaveFrontendServer tls config error"))?
+        .add_service(TeaclaveStorageServer::new(service))
+        .serve(listen_address)
+        .await?;
+    storage_handle.join().unwrap();
     Ok(())
 }
 
@@ -132,10 +131,16 @@
 
 #[handle_ecall]
 fn handle_start_service(input: &StartServiceInput) -> TeeServiceResult<StartServiceOutput> {
-    match start_service(&input.config) {
+    let result = tokio::runtime::Builder::new_current_thread()
+        .enable_all()
+        .build()
+        .map_err(|_| TeeServiceError::SgxError)?
+        .block_on(start_service(&input.config));
+
+    match result {
         Ok(_) => Ok(StartServiceOutput),
         Err(e) => {
-            log::error!("Failed to start the service: {}", e);
+            error!("Failed to run service: {}", e);
             Err(TeeServiceError::ServiceError)
         }
     }
diff --git a/services/storage/enclave/src/proxy.rs b/services/storage/enclave/src/proxy.rs
index c863314..a2bfdfc 100644
--- a/services/storage/enclave/src/proxy.rs
+++ b/services/storage/enclave/src/proxy.rs
@@ -17,41 +17,79 @@
 
 use crate::error::StorageServiceError;
 use anyhow::anyhow;
-use std::sync::mpsc::{channel, Sender};
-use teaclave_proto::teaclave_storage_service::{TeaclaveStorageRequest, TeaclaveStorageResponse};
-use teaclave_rpc::Request;
-use teaclave_types::TeaclaveServiceResponseResult;
+use teaclave_proto::teaclave_storage_service::*;
+use teaclave_rpc::{Request, Response, Status};
+use tokio::sync::mpsc::{unbounded_channel, UnboundedSender};
 
 #[derive(Clone)]
 pub(crate) struct ProxyService {
-    sender: Sender<ProxyRequest>,
+    sender: UnboundedSender<ProxyRequest>,
 }
 
 impl ProxyService {
-    pub(crate) fn new(sender: Sender<ProxyRequest>) -> Self {
+    pub(crate) fn new(sender: UnboundedSender<ProxyRequest>) -> Self {
         Self { sender }
     }
 }
 
-impl teaclave_rpc::TeaclaveService<TeaclaveStorageRequest, TeaclaveStorageResponse>
-    for ProxyService
-{
-    fn handle_request(
-        &self,
-        request: Request<TeaclaveStorageRequest>,
-    ) -> TeaclaveServiceResponseResult<TeaclaveStorageResponse> {
-        let (sender, receiver) = channel();
-        self.sender
-            .send(ProxyRequest { sender, request })
+macro_rules! send_request {
+    ($service: ident,$request:expr,$fun:ident) => {{
+        let (sender, mut receiver) = unbounded_channel();
+        let request = $request.into_inner();
+        $service
+            .sender
+            .send(ProxyRequest {
+                sender,
+                request: Request::new(TeaclaveStorageRequest::$fun(request)),
+            })
             .map_err(|_| StorageServiceError::Service(anyhow!("send ProxyRequest error")))?;
-        receiver
-            .recv()
-            .map_err(|_| StorageServiceError::Service(anyhow!("recv ProxyRequest error")))?
+        match receiver.recv().await {
+            Some(Ok(TeaclaveStorageResponse::$fun(re))) => return Ok(Response::new(re)),
+            _ => return Err(teaclave_rpc::Status::internal("invalid response")),
+        }
+    }};
+}
+
+#[teaclave_rpc::async_trait]
+impl TeaclaveStorage for ProxyService {
+    async fn get(&self, request: Request<GetRequest>) -> Result<Response<GetResponse>, Status> {
+        send_request!(self, request, Get)
+    }
+
+    async fn put(&self, request: Request<PutRequest>) -> Result<Response<PutResponse>, Status> {
+        send_request!(self, request, Put)
+    }
+
+    async fn delete(
+        &self,
+        request: Request<DeleteRequest>,
+    ) -> Result<Response<DeleteResponse>, Status> {
+        send_request!(self, request, Delete)
+    }
+
+    async fn enqueue(
+        &self,
+        request: Request<EnqueueRequest>,
+    ) -> Result<Response<EnqueueResponse>, Status> {
+        send_request!(self, request, Enqueue)
+    }
+
+    async fn dequeue(
+        &self,
+        request: Request<DequeueRequest>,
+    ) -> Result<Response<DequeueResponse>, Status> {
+        send_request!(self, request, Dequeue)
+    }
+
+    async fn get_keys_by_prefix(
+        &self,
+        request: Request<GetKeysByPrefixRequest>,
+    ) -> Result<Response<GetKeysByPrefixResponse>, Status> {
+        send_request!(self, request, GetKeysByPrefix)
     }
 }
 
-#[derive(Clone)]
 pub(crate) struct ProxyRequest {
-    pub sender: Sender<TeaclaveServiceResponseResult<TeaclaveStorageResponse>>,
+    pub sender: UnboundedSender<std::result::Result<TeaclaveStorageResponse, StorageServiceError>>,
     pub request: Request<TeaclaveStorageRequest>,
 }
diff --git a/services/storage/enclave/src/service.rs b/services/storage/enclave/src/service.rs
index a001950..9a98890 100644
--- a/services/storage/enclave/src/service.rs
+++ b/services/storage/enclave/src/service.rs
@@ -21,23 +21,20 @@
 use rusty_leveldb::LdbIterator;
 use rusty_leveldb::DB;
 use std::cell::RefCell;
-use std::sync::mpsc::Receiver;
 use teaclave_proto::teaclave_storage_service::*;
-use teaclave_rpc::Request;
-use teaclave_service_enclave_utils::{bail, teaclave_service};
-use teaclave_types::TeaclaveServiceResponseResult;
+use teaclave_service_enclave_utils::bail;
+use tokio::sync::mpsc::UnboundedReceiver;
 
-#[teaclave_service(teaclave_storage_service, TeaclaveStorage, StorageServiceError)]
 pub(crate) struct TeaclaveStorageService {
     // Current LevelDB implementation is not concurrent, so we need to wrap the
     // DB with RefCell. This service is running in a single thread, it's safe to
     // use RefCell.
     database: RefCell<DB>,
-    receiver: Receiver<ProxyRequest>,
+    receiver: UnboundedReceiver<ProxyRequest>,
 }
 
 impl TeaclaveStorageService {
-    pub(crate) fn new(database: RefCell<DB>, receiver: Receiver<ProxyRequest>) -> Self {
+    pub(crate) fn new(database: RefCell<DB>, receiver: UnboundedReceiver<ProxyRequest>) -> Self {
         Self { database, receiver }
     }
 }
@@ -156,14 +153,7 @@
 
 impl TeaclaveStorageService {
     pub(crate) fn start(&mut self) {
-        loop {
-            let request = match self.receiver.recv() {
-                Ok(req) => req,
-                Err(e) => {
-                    error!("mspc receive error: {}", e);
-                    break;
-                }
-            };
+        while let Some(request) = self.receiver.blocking_recv() {
             let database_request = request.request;
             let sender = request.sender;
             let response = self.dispatch(database_request);
@@ -174,18 +164,49 @@
             }
         }
     }
+
+    fn dispatch(
+        &self,
+        request: teaclave_rpc::Request<TeaclaveStorageRequest>,
+    ) -> std::result::Result<TeaclaveStorageResponse, StorageServiceError> {
+        match request.into_inner() {
+            TeaclaveStorageRequest::Get(r) => {
+                let response = self.get(r)?;
+                Ok(response).map(TeaclaveStorageResponse::Get)
+            }
+            TeaclaveStorageRequest::Put(r) => {
+                let response = self.put(r)?;
+                Ok(response).map(TeaclaveStorageResponse::Put)
+            }
+            TeaclaveStorageRequest::Delete(r) => {
+                let response = self.delete(r)?;
+                Ok(response).map(TeaclaveStorageResponse::Delete)
+            }
+            TeaclaveStorageRequest::Enqueue(r) => {
+                let response = self.enqueue(r)?;
+                Ok(response).map(TeaclaveStorageResponse::Enqueue)
+            }
+            TeaclaveStorageRequest::Dequeue(r) => {
+                let response = self.dequeue(r)?;
+                Ok(response).map(TeaclaveStorageResponse::Dequeue)
+            }
+            TeaclaveStorageRequest::GetKeysByPrefix(r) => {
+                let response = self.get_keys_by_prefix(r)?;
+                Ok(response).map(TeaclaveStorageResponse::GetKeysByPrefix)
+            }
+        }
+    }
 }
-impl TeaclaveStorage for TeaclaveStorageService {
-    fn get(&self, request: Request<GetRequest>) -> TeaclaveServiceResponseResult<GetResponse> {
-        let request = request.message;
+
+impl TeaclaveStorageService {
+    fn get(&self, request: GetRequest) -> std::result::Result<GetResponse, StorageServiceError> {
         match self.database.borrow_mut().get(&request.key) {
             Some(value) => Ok(GetResponse { value }),
             None => bail!(StorageServiceError::None),
         }
     }
 
-    fn put(&self, request: Request<PutRequest>) -> TeaclaveServiceResponseResult<PutResponse> {
-        let request = request.message;
+    fn put(&self, request: PutRequest) -> std::result::Result<PutResponse, StorageServiceError> {
         self.database
             .borrow_mut()
             .put(&request.key, &request.value)
@@ -195,14 +216,13 @@
             .borrow_mut()
             .flush()
             .map_err(StorageServiceError::Database)?;
-        Ok(PutResponse)
+        Ok(PutResponse {})
     }
 
     fn delete(
         &self,
-        request: Request<DeleteRequest>,
-    ) -> TeaclaveServiceResponseResult<DeleteResponse> {
-        let request = request.message;
+        request: DeleteRequest,
+    ) -> std::result::Result<DeleteResponse, StorageServiceError> {
         self.database
             .borrow_mut()
             .delete(&request.key)
@@ -212,14 +232,13 @@
             .borrow_mut()
             .flush()
             .map_err(StorageServiceError::Database)?;
-        Ok(DeleteResponse)
+        Ok(DeleteResponse {})
     }
 
     fn enqueue(
         &self,
-        request: Request<EnqueueRequest>,
-    ) -> TeaclaveServiceResponseResult<EnqueueResponse> {
-        let request = request.message;
+        request: EnqueueRequest,
+    ) -> std::result::Result<EnqueueResponse, StorageServiceError> {
         let mut db = self.database.borrow_mut();
         let mut queue = DBQueue::open(&mut db, &request.key);
         match queue.enqueue(&request.value) {
@@ -230,9 +249,8 @@
 
     fn dequeue(
         &self,
-        request: Request<DequeueRequest>,
-    ) -> TeaclaveServiceResponseResult<DequeueResponse> {
-        let request = request.message;
+        request: DequeueRequest,
+    ) -> std::result::Result<DequeueResponse, StorageServiceError> {
         let mut db = self.database.borrow_mut();
         let mut queue = DBQueue::open(&mut db, &request.key);
         match queue.dequeue() {
@@ -243,9 +261,9 @@
 
     fn get_keys_by_prefix(
         &self,
-        request: Request<GetKeysByPrefixRequest>,
-    ) -> TeaclaveServiceResponseResult<GetKeysByPrefixResponse> {
-        let prefix = request.message.prefix;
+        request: GetKeysByPrefixRequest,
+    ) -> std::result::Result<GetKeysByPrefixResponse, StorageServiceError> {
+        let prefix = request.prefix;
         let mut db = self.database.borrow_mut();
         let mut it = db.new_iter().map_err(StorageServiceError::Database)?;
 
@@ -280,11 +298,10 @@
 #[cfg(feature = "enclave_unit_test")]
 pub mod tests {
     use super::*;
-    use std::sync::mpsc::channel;
-    use teaclave_rpc::IntoRequest;
+    use tokio::sync::mpsc::unbounded_channel;
 
     fn get_mock_service() -> TeaclaveStorageService {
-        let (_sender, receiver) = channel();
+        let (_sender, receiver) = unbounded_channel();
         let key = [
             0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a,
             0x09, 0x08,
@@ -303,61 +320,61 @@
 
     pub fn test_get_key() {
         let service = get_mock_service();
-        let request = GetRequest::new("test_get_key").into_request();
+        let request = GetRequest::new("test_get_key");
         assert!(service.get(request).is_ok());
     }
 
     pub fn test_put_key() {
         let service = get_mock_service();
-        let request = PutRequest::new("test_put_key", "test_put_value").into_request();
+        let request = PutRequest::new("test_put_key", "test_put_value");
         assert!(service.put(request).is_ok());
-        let request = GetRequest::new("test_put_key").into_request();
+        let request = GetRequest::new("test_put_key");
         assert!(service.get(request).is_ok());
     }
 
     pub fn test_delete_key() {
         let service = get_mock_service();
-        let request = DeleteRequest::new("test_delete_key").into_request();
+        let request = DeleteRequest::new("test_delete_key");
         assert!(service.delete(request).is_ok());
-        let request = GetRequest::new("test_delete_key").into_request();
+        let request = GetRequest::new("test_delete_key");
         assert!(service.get(request).is_err());
     }
 
     pub fn test_enqueue() {
         let service = get_mock_service();
-        let request = EnqueueRequest::new("test_enqueue_key", "1").into_request();
+        let request = EnqueueRequest::new("test_enqueue_key", "1");
         assert!(service.enqueue(request).is_ok());
-        let request = EnqueueRequest::new("test_enqueue_key", "2").into_request();
+        let request = EnqueueRequest::new("test_enqueue_key", "2");
         assert!(service.enqueue(request).is_ok());
     }
 
     pub fn test_dequeue() {
         let service = get_mock_service();
-        let request = DequeueRequest::new("test_dequeue_key").into_request();
+        let request = DequeueRequest::new("test_dequeue_key");
         assert!(service.dequeue(request).is_err());
-        let request = EnqueueRequest::new("test_dequeue_key", "1").into_request();
+        let request = EnqueueRequest::new("test_dequeue_key", "1");
         assert!(service.enqueue(request).is_ok());
-        let request = EnqueueRequest::new("test_dequeue_key", "2").into_request();
+        let request = EnqueueRequest::new("test_dequeue_key", "2");
         assert!(service.enqueue(request).is_ok());
-        let request = DequeueRequest::new("test_dequeue_key").into_request();
+        let request = DequeueRequest::new("test_dequeue_key");
         assert_eq!(service.dequeue(request).unwrap().value, b"1");
-        let request = DequeueRequest::new("test_dequeue_key").into_request();
+        let request = DequeueRequest::new("test_dequeue_key");
         assert_eq!(service.dequeue(request).unwrap().value, b"2");
     }
 
     pub fn test_get_keys_by_prefix() {
         let service = get_mock_service();
-        let request = PutRequest::new("function-1", "test_put_value").into_request();
+        let request = PutRequest::new("function-1", "test_put_value");
         assert!(service.put(request).is_ok());
-        let request = PutRequest::new("function-22", "test_put_value").into_request();
+        let request = PutRequest::new("function-22", "test_put_value");
         assert!(service.put(request).is_ok());
-        let request = PutRequest::new("function-333", "test_put_value").into_request();
+        let request = PutRequest::new("function-333", "test_put_value");
         assert!(service.put(request).is_ok());
-        let request = PutRequest::new("task-444", "test_put_value").into_request();
+        let request = PutRequest::new("task-444", "test_put_value");
         assert!(service.put(request).is_ok());
-        let request = PutRequest::new("function-5", "test_put_value").into_request();
+        let request = PutRequest::new("function-5", "test_put_value");
         assert!(service.put(request).is_ok());
-        let request = GetKeysByPrefixRequest::new("function").into_request();
+        let request = GetKeysByPrefixRequest::new("function");
         let response = service.get_keys_by_prefix(request);
         assert!(response.is_ok());
         assert_eq!(
diff --git a/services/utils/service_enclave_utils/Cargo.toml b/services/utils/service_enclave_utils/Cargo.toml
index bb4100b..87628e2 100644
--- a/services/utils/service_enclave_utils/Cargo.toml
+++ b/services/utils/service_enclave_utils/Cargo.toml
@@ -32,7 +32,7 @@
 ]
 libos = [ 
     "teaclave_attestation/libos",
-    "teaclave_rpc/app",
+    "teaclave_rpc/libos",
     "teaclave_types/app",
 ]
 cov = ["sgx_cov", "sgx_macros"]
@@ -41,13 +41,13 @@
 anyhow     = { version = "1.0.26" }
 env_logger = { version = "0.9.3", default_features = false }
 log        = { version = "0.4.17", features = ["release_max_level_info"] }
+tokio      = { version = "1.0", features = ["rt-multi-thread", "time", "macros"] }
 
 teaclave_attestation                      = { path = "../../../attestation" }
 teaclave_config                           = { path = "../../../config" }
 teaclave_logger                           = { path = "../../../logger" }
 teaclave_proto                            = { path = "../../proto" }
 teaclave_rpc                              = { path = "../../../rpc" }
-teaclave_service_enclave_utils_proc_macro = { path = "./proc_macro" }
 teaclave_types                            = { path = "../../../types" }
 
 sgx_cov     = { version = "2.0.0", optional = true }
diff --git a/services/utils/service_enclave_utils/proc_macro/Cargo.toml b/services/utils/service_enclave_utils/proc_macro/Cargo.toml
deleted file mode 100644
index aea23f3..0000000
--- a/services/utils/service_enclave_utils/proc_macro/Cargo.toml
+++ /dev/null
@@ -1,33 +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.
-
-[package]
-name = "teaclave_service_enclave_utils_proc_macro"
-version = "0.5.1"
-authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
-description = "Procedure macro for service enclave utilities"
-license = "Apache-2.0"
-edition = "2021"
-publish = false
-
-[lib]
-proc-macro = true
-
-[dependencies]
-proc-macro2 = "1.0"
-quote = "1.0"
-syn = { version = "1.0", features = ["full"] }
diff --git a/services/utils/service_enclave_utils/proc_macro/src/lib.rs b/services/utils/service_enclave_utils/proc_macro/src/lib.rs
deleted file mode 100644
index e22982b..0000000
--- a/services/utils/service_enclave_utils/proc_macro/src/lib.rs
+++ /dev/null
@@ -1,57 +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.
-
-extern crate proc_macro;
-use proc_macro2::{Ident, Span};
-use quote::quote;
-use syn::parse_macro_input;
-use syn::ItemStruct;
-
-use proc_macro::TokenStream;
-
-#[proc_macro_attribute]
-pub fn teaclave_service(attr: TokenStream, input: TokenStream) -> TokenStream {
-    let attr_str = attr.to_string();
-    let splits: Vec<&str> = attr_str.split(',').map(|s| s.trim()).collect();
-    let crate_name = Ident::new(splits[0], Span::call_site());
-    let crate_name_proto = Ident::new(&format!("{}_proto", crate_name), Span::call_site());
-    let trait_name = splits[1];
-    let trait_name_ident = Ident::new(trait_name, Span::call_site());
-    let request = Ident::new(&format!("{}Request", trait_name), Span::call_site());
-    let response = Ident::new(&format!("{}Response", trait_name), Span::call_site());
-
-    let f = parse_macro_input!(input as ItemStruct);
-    let struct_ident = &f.ident;
-    let q = quote!(
-        #f
-
-        impl teaclave_rpc::TeaclaveService<teaclave_proto::#crate_name_proto::#request, teaclave_proto::#crate_name_proto::#response>
-            for #struct_ident
-        {
-            fn handle_request(
-                &self,
-                request: teaclave_rpc::Request<teaclave_proto::#crate_name_proto::#request>,
-            ) -> std::result::Result<teaclave_proto::#crate_name_proto::#response, teaclave_types::TeaclaveServiceResponseError> {
-                use teaclave_proto::#crate_name_proto::#trait_name_ident;
-                use log::trace;
-                trace!("Dispatching request.");
-                self.dispatch(request)
-            }
-        }
-    );
-    q.into()
-}
diff --git a/services/utils/service_enclave_utils/src/lib.rs b/services/utils/service_enclave_utils/src/lib.rs
index 0c16a4e..0a9be50 100644
--- a/services/utils/service_enclave_utils/src/lib.rs
+++ b/services/utils/service_enclave_utils/src/lib.rs
@@ -32,8 +32,6 @@
 use teaclave_attestation::verifier::AttestationReportVerificationFn;
 use teaclave_attestation::AttestedTlsConfig;
 use teaclave_config::RuntimeConfig;
-use teaclave_rpc::config::SgxTrustedTlsClientConfig;
-use teaclave_rpc::endpoint::Endpoint;
 use teaclave_types::{EnclaveInfo, TeeServiceResult};
 
 mod macros;
@@ -121,8 +119,6 @@
     Ok(sub_base)
 }
 
-pub use teaclave_service_enclave_utils_proc_macro::teaclave_service;
-
 macro_rules! impl_create_trusted_endpoint_fn {
     ($fn_name:ident, $enclave_attr:literal) => {
         pub fn $fn_name(
@@ -131,20 +127,28 @@
             as_root_ca_cert: &[u8],
             verifier: AttestationReportVerificationFn,
             attested_tls_config: Arc<RwLock<AttestedTlsConfig>>,
-        ) -> Result<Endpoint> {
+        ) -> Result<teaclave_rpc::transport::channel::Endpoint> {
             let service_enclave_attrs = enclave_info
                 .get_enclave_attr($enclave_attr)
-                .expect("enclave_info");
-            let service_client_config =
-                SgxTrustedTlsClientConfig::from_attested_tls_config(attested_tls_config)?
-                    .attestation_report_verifier(
-                        vec![service_enclave_attrs],
-                        as_root_ca_cert,
-                        verifier,
-                    );
-            let service_address = &advertised_address;
+                .expect("enclave attr");
+            let client_tls_config =
+                teaclave_rpc::config::SgxTrustedTlsClientConfig::from_attested_tls_config(
+                    attested_tls_config,
+                )?
+                .attestation_report_verifier(vec![service_enclave_attrs], as_root_ca_cert, verifier)
+                .into();
 
-            Ok(Endpoint::new(service_address).config(service_client_config))
+            let dst = advertised_address.parse::<teaclave_rpc::transport::Uri>()?;
+            if dst.scheme().is_none() {
+                anyhow::bail!(format!(
+                    "Missing schema in {} advertised address",
+                    stringify!($enclave_attr)
+                ));
+            };
+            let endpoint = teaclave_rpc::transport::Channel::builder(dst)
+                .tls_config(client_tls_config)?
+                .connect_timeout(std::time::Duration::from_secs(30));
+            Ok(endpoint)
         }
     };
 }
diff --git a/tests/functional/enclave/Cargo.toml b/tests/functional/enclave/Cargo.toml
index 3cd9a51..c4ea0e3 100644
--- a/tests/functional/enclave/Cargo.toml
+++ b/tests/functional/enclave/Cargo.toml
@@ -45,12 +45,14 @@
 
 [dependencies]
 anyhow      = { version = "1.0.26" }
+futures     = { version = "0.3" }
 inventory   = { version = "0.1.6" }
 lazy_static = { version = "1.4.0" }
 log         = { version = "0.4.17", features = ["release_max_level_info"] }
 serde       = { version = "1.0.92" }
 serde_json  = { version = "1.0.39" }
 thiserror   = { version = "1.0.9" }
+tokio       = { version = "1.0", features = ["rt-multi-thread", "time", "macros"] }
 url         = { version = "2.1.1" }
 uuid        = { version = "0.8.1", features = ["v4"] }
 
diff --git a/tests/functional/enclave/Enclave.config.xml b/tests/functional/enclave/Enclave.config.xml
index 9c52ef6..a2bf9d0 100644
--- a/tests/functional/enclave/Enclave.config.xml
+++ b/tests/functional/enclave/Enclave.config.xml
@@ -23,7 +23,7 @@
   <ISVSVN>0</ISVSVN>
   <StackMaxSize>0x200000</StackMaxSize>
   <HeapMaxSize>0x1000000</HeapMaxSize>
-  <TCSNum>22</TCSNum>
+  <TCSNum>24</TCSNum>
   <TCSPolicy>0</TCSPolicy>
   <DisableDebug>0</DisableDebug>
   <MiscSelect>0</MiscSelect>
diff --git a/tests/functional/enclave/src/access_control_service.rs b/tests/functional/enclave/src/access_control_service.rs
index 5d46028..b52f80d 100644
--- a/tests/functional/enclave/src/access_control_service.rs
+++ b/tests/functional/enclave/src/access_control_service.rs
@@ -16,93 +16,93 @@
 // under the License.
 
 use crate::utils::*;
+use futures::FutureExt;
 use teaclave_proto::teaclave_access_control_service::*;
-use teaclave_test_utils::test_case;
-
-#[test_case]
-fn test_authorize_data_success() {
-    let mut client = get_access_control_client();
+use teaclave_test_utils::async_test_case;
+#[async_test_case]
+async fn test_authorize_data_success() {
+    let mut client = get_access_control_client().await;
 
     let request = AuthorizeDataRequest::new("mock_user_a", "mock_data");
-    let response_result = client.authorize_data(request);
+    let response_result = client.authorize_data(request).await;
     assert!(response_result.is_ok());
-    assert!(response_result.unwrap().accept);
+    assert!(response_result.unwrap().into_inner().accept);
 }
 
-#[test_case]
-fn test_authorize_data_fail() {
-    let mut client = get_access_control_client();
+#[async_test_case]
+async fn test_authorize_data_fail() {
+    let mut client = get_access_control_client().await;
 
     let request = AuthorizeDataRequest::new("mock_user_d", "mock_data");
-    let response_result = client.authorize_data(request);
+    let response_result = client.authorize_data(request).await;
     assert!(response_result.is_ok());
-    assert!(!response_result.unwrap().accept);
+    assert!(!response_result.unwrap().into_inner().accept);
 
     let request = AuthorizeDataRequest::new("mock_user_a", "mock_data_b");
-    let response_result = client.authorize_data(request);
+    let response_result = client.authorize_data(request).await;
     assert!(response_result.is_ok());
-    assert!(!response_result.unwrap().accept);
+    assert!(!response_result.unwrap().into_inner().accept);
 }
 
-#[test_case]
-fn test_authorize_function_success() {
-    let mut client = get_access_control_client();
+#[async_test_case]
+async fn test_authorize_function_success() {
+    let mut client = get_access_control_client().await;
 
     let request =
         AuthorizeFunctionRequest::new("mock_public_function_owner", "mock_public_function");
-    let response_result = client.authorize_function(request);
+    let response_result = client.authorize_function(request).await;
     assert!(response_result.is_ok());
-    assert!(response_result.unwrap().accept);
+    assert!(response_result.unwrap().into_inner().accept);
 
     let request =
         AuthorizeFunctionRequest::new("mock_private_function_owner", "mock_private_function");
-    let response_result = client.authorize_function(request);
+    let response_result = client.authorize_function(request).await;
     assert!(response_result.is_ok());
-    assert!(response_result.unwrap().accept);
+    assert!(response_result.unwrap().into_inner().accept);
 
     let request =
         AuthorizeFunctionRequest::new("mock_private_function_owner", "mock_public_function");
-    let response_result = client.authorize_function(request);
+    let response_result = client.authorize_function(request).await;
     assert!(response_result.is_ok());
-    assert!(response_result.unwrap().accept);
+    assert!(response_result.unwrap().into_inner().accept);
 }
 
-#[test_case]
-fn test_authorize_function_fail() {
-    let mut client = get_access_control_client();
+#[async_test_case]
+async fn test_authorize_function_fail() {
+    let mut client = get_access_control_client().await;
     let request =
         AuthorizeFunctionRequest::new("mock_public_function_owner", "mock_private_function");
-    let response_result = client.authorize_function(request);
+    let response_result = client.authorize_function(request).await;
     assert!(response_result.is_ok());
-    assert!(!response_result.unwrap().accept);
+    assert!(!response_result.unwrap().into_inner().accept);
 }
 
-#[test_case]
-fn test_authorize_task_success() {
-    let mut client = get_access_control_client();
+#[async_test_case]
+async fn test_authorize_task_success() {
+    let mut client = get_access_control_client().await;
     let request = AuthorizeTaskRequest::new("mock_participant_a", "mock_task");
-    let response_result = client.authorize_task(request);
+    let response_result = client.authorize_task(request).await;
     assert!(response_result.is_ok());
-    assert!(response_result.unwrap().accept);
+    assert!(response_result.unwrap().into_inner().accept);
 
     let request = AuthorizeTaskRequest::new("mock_participant_b", "mock_task");
-    let response_result = client.authorize_task(request);
+    let response_result = client.authorize_task(request).await;
     assert!(response_result.is_ok());
-    assert!(response_result.unwrap().accept);
+    assert!(response_result.unwrap().into_inner().accept);
 }
 
-#[test_case]
-fn test_authorize_task_fail() {
-    let mut client = get_access_control_client();
+#[async_test_case]
+async fn test_authorize_task_fail() {
+    let mut client = get_access_control_client().await;
     let request = AuthorizeTaskRequest::new("mock_participant_c", "mock_task");
-    let response_result = client.authorize_task(request);
+    let response_result = client.authorize_task(request).await;
     assert!(response_result.is_ok());
-    assert!(!response_result.unwrap().accept);
+    assert!(!response_result.unwrap().into_inner().accept);
 }
 
-#[test_case]
-fn test_authorize_staged_task_success() {
-    let mut client = get_access_control_client();
+#[async_test_case]
+async fn test_authorize_staged_task_success() {
+    let mut client = get_access_control_client().await;
     let request = AuthorizeStagedTaskRequest {
         subject_task_id: "mock_staged_task".to_string(),
         object_function_id: "mock_staged_allowed_private_function".to_string(),
@@ -117,23 +117,23 @@
             "mock_staged_allowed_data3".to_string(),
         ],
     };
-    let response_result = client.authorize_staged_task(request);
+    let response_result = client.authorize_staged_task(request).await;
     assert!(response_result.is_ok());
-    assert!(response_result.unwrap().accept);
+    assert!(response_result.unwrap().into_inner().accept);
 }
 
-#[test_case]
-fn test_authorize_staged_task_fail() {
-    let mut client = get_access_control_client();
+#[async_test_case]
+async fn test_authorize_staged_task_fail() {
+    let mut client = get_access_control_client().await;
     let request = AuthorizeStagedTaskRequest {
         subject_task_id: "mock_staged_task".to_string(),
         object_function_id: "mock_staged_disallowed_private_function".to_string(),
         object_input_data_id_list: vec![],
         object_output_data_id_list: vec![],
     };
-    let response_result = client.authorize_staged_task(request);
+    let response_result = client.authorize_staged_task(request).await;
     assert!(response_result.is_ok());
-    assert!(!response_result.unwrap().accept);
+    assert!(!response_result.unwrap().into_inner().accept);
 
     let request = AuthorizeStagedTaskRequest {
         subject_task_id: "mock_staged_task".to_string(),
@@ -141,9 +141,9 @@
         object_input_data_id_list: vec!["mock_staged_disallowed_data1".to_string()],
         object_output_data_id_list: vec![],
     };
-    let response_result = client.authorize_staged_task(request);
+    let response_result = client.authorize_staged_task(request).await;
     assert!(response_result.is_ok());
-    assert!(!response_result.unwrap().accept);
+    assert!(!response_result.unwrap().into_inner().accept);
 
     let request = AuthorizeStagedTaskRequest {
         subject_task_id: "mock_staged_task".to_string(),
@@ -151,21 +151,21 @@
         object_input_data_id_list: vec![],
         object_output_data_id_list: vec!["mock_staged_disallowed_data2".to_string()],
     };
-    let response_result = client.authorize_staged_task(request);
+    let response_result = client.authorize_staged_task(request).await;
     assert!(response_result.is_ok());
-    assert!(!response_result.unwrap().accept);
+    assert!(!response_result.unwrap().into_inner().accept);
 }
 
-#[test_case]
-fn test_concurrency() {
+#[async_test_case]
+async fn test_concurrency() {
     let mut thread_pool = Vec::new();
     for _i in 0..10 {
-        let child = std::thread::spawn(move || {
+        let child = std::thread::spawn(move || async {
             for _j in 0..10 {
-                test_authorize_data_fail();
-                test_authorize_function_fail();
-                test_authorize_task_success();
-                test_authorize_staged_task_fail();
+                test_authorize_data_fail().await;
+                test_authorize_function_fail().await;
+                test_authorize_task_success().await;
+                test_authorize_staged_task_fail().await;
             }
         });
         thread_pool.push(child);
diff --git a/tests/functional/enclave/src/authentication_service.rs b/tests/functional/enclave/src/authentication_service.rs
index 258f117..b975794 100644
--- a/tests/functional/enclave/src/authentication_service.rs
+++ b/tests/functional/enclave/src/authentication_service.rs
@@ -15,142 +15,107 @@
 // specific language governing permissions and limitations
 // under the License.
 
-use teaclave_attestation::verifier;
-use teaclave_config::build::AS_ROOT_CA_CERT;
+use crate::utils::*;
+use futures::FutureExt;
 use teaclave_config::RuntimeConfig;
 use teaclave_proto::teaclave_authentication_service::*;
 use teaclave_proto::teaclave_common::*;
-use teaclave_rpc::config::SgxTrustedTlsClientConfig;
-use teaclave_rpc::endpoint::Endpoint;
-use teaclave_test_utils::test_case;
+use teaclave_rpc::{
+    transport::{Channel, Uri},
+    CredentialService,
+};
+use teaclave_test_utils::async_test_case;
 use teaclave_types::EnclaveInfo;
-
-use crate::utils::shared_admin_credential;
-use std::collections::HashMap;
-
-fn get_api_client() -> TeaclaveAuthenticationApiClient {
+async fn get_api_client() -> TeaclaveAuthenticationApiClient<CredentialService> {
     let runtime_config = RuntimeConfig::from_toml("runtime.config.toml").expect("runtime");
     let enclave_info = EnclaveInfo::from_bytes(&runtime_config.audit.enclave_info_bytes);
-    let enclave_attr = enclave_info
-        .get_enclave_attr("teaclave_authentication_service")
-        .expect("authentication");
-    let config = SgxTrustedTlsClientConfig::new().attestation_report_verifier(
-        vec![enclave_attr],
-        AS_ROOT_CA_CERT,
-        verifier::universal_quote_verifier,
-    );
-
-    let channel = Endpoint::new("localhost:7776")
-        .config(config)
-        .connect()
-        .unwrap();
-    TeaclaveAuthenticationApiClient::new(channel).unwrap()
+    create_authentication_api_client(&enclave_info, "https://localhost:7776")
+        .await
+        .unwrap()
 }
 
-fn get_api_client_with_credential(cred: &UserCredential) -> TeaclaveAuthenticationApiClient {
+async fn get_internal_client() -> TeaclaveAuthenticationInternalClient<CredentialService> {
     let runtime_config = RuntimeConfig::from_toml("runtime.config.toml").expect("runtime");
     let enclave_info = EnclaveInfo::from_bytes(&runtime_config.audit.enclave_info_bytes);
-    let enclave_attr = enclave_info
-        .get_enclave_attr("teaclave_authentication_service")
-        .expect("authentication");
-    let config = SgxTrustedTlsClientConfig::new().attestation_report_verifier(
-        vec![enclave_attr],
-        AS_ROOT_CA_CERT,
-        verifier::universal_quote_verifier,
-    );
-
-    let channel = Endpoint::new("localhost:7776")
-        .config(config)
+    let tls_config =
+        create_client_config(&enclave_info, "teaclave_authentication_service").unwrap();
+    let service_addr = runtime_config
+        .internal_endpoints
+        .authentication
+        .advertised_address;
+    let endpoint = Channel::builder(service_addr.parse::<Uri>().unwrap());
+    let channel = endpoint
+        .tls_config(tls_config)
+        .unwrap()
         .connect()
+        .await
         .unwrap();
-    let mut metadata = HashMap::new();
-    metadata.insert("id".to_string(), cred.id.to_owned());
-    metadata.insert("token".to_string(), cred.token.to_owned());
-    TeaclaveAuthenticationApiClient::new_with_metadata(channel, metadata).unwrap()
-}
-
-fn get_internal_client() -> TeaclaveAuthenticationInternalClient {
-    let runtime_config = RuntimeConfig::from_toml("runtime.config.toml").expect("runtime");
-    let enclave_info = EnclaveInfo::from_bytes(&runtime_config.audit.enclave_info_bytes);
-    let enclave_attr = enclave_info
-        .get_enclave_attr("teaclave_authentication_service")
-        .expect("authentication");
-    let config = SgxTrustedTlsClientConfig::new().attestation_report_verifier(
-        vec![enclave_attr],
-        AS_ROOT_CA_CERT,
-        verifier::universal_quote_verifier,
-    );
-
-    let channel = Endpoint::new(
-        &runtime_config
-            .internal_endpoints
-            .authentication
-            .advertised_address,
+    TeaclaveAuthenticationInternalClient::with_interceptor(
+        channel,
+        teaclave_rpc::UserCredential::default(),
     )
-    .config(config)
-    .connect()
-    .unwrap();
-    TeaclaveAuthenticationInternalClient::new(channel).unwrap()
 }
 
-#[test_case]
-fn test_login_success() {
-    debug!("{:?}", shared_admin_credential());
-    let mut client = get_api_client_with_credential(shared_admin_credential());
+#[async_test_case]
+async fn test_login_success() {
+    let mut client = get_api_client_with_admin_credential().await;
     let request = UserRegisterRequest::new("test_login_id1", "test_password", "PlatformAdmin", "");
-    let response_result = client.user_register(request);
+    let response_result = client.user_register(request).await;
     let _ = response_result.unwrap();
 
-    let mut client = get_api_client();
+    let mut client = get_api_client().await;
     let request = UserLoginRequest::new("test_login_id1", "test_password");
-    let response_result = client.user_login(request);
+    let response_result = client.user_login(request).await;
     debug!("{:?}", response_result);
     assert!(response_result.is_ok());
 }
 
-#[test_case]
-fn test_login_fail() {
-    let mut client = get_api_client_with_credential(shared_admin_credential());
+#[async_test_case]
+async fn test_login_fail() {
+    let mut client = get_api_client_with_admin_credential().await;
     let request = UserRegisterRequest::new("test_login_id2", "test_password", "PlatformAdmin", "");
-    let response_result = client.user_register(request);
+    let response_result = client.user_register(request).await;
     assert!(response_result.is_ok());
 
-    let mut client = get_api_client();
+    let mut client = get_api_client().await;
     let request = UserLoginRequest::new("test_login_id2", "wrong_password");
-    let response_result = client.user_login(request);
+    let response_result = client.user_login(request).await;
     debug!("{:?}", response_result);
     assert!(response_result.is_err());
 }
 
-#[test_case]
-fn test_authenticate_success() {
-    let mut api_client = get_api_client_with_credential(shared_admin_credential());
+#[async_test_case]
+async fn test_authenticate_success() {
+    let mut api_client = get_api_client_with_admin_credential().await;
     let request = UserRegisterRequest::new(
         "test_authenticate_id1",
         "test_password",
         "PlatformAdmin",
         "",
     );
-    let response_result = api_client.user_register(request);
+    let response_result = api_client.user_register(request).await;
     assert!(response_result.is_ok());
 
-    let mut api_client = get_api_client();
+    let mut api_client = get_api_client().await;
     let request = UserLoginRequest::new("test_authenticate_id1", "test_password");
-    let response_result = api_client.user_login(request);
+    let response_result = api_client.user_login(request).await;
     assert!(response_result.is_ok());
 
-    let mut internal_client = get_internal_client();
-    let credential = UserCredential::new("test_authenticate_id1", response_result.unwrap().token);
+    let mut internal_client = get_internal_client().await;
+    let credential = UserCredential::new(
+        "test_authenticate_id1",
+        response_result.unwrap().into_inner().token,
+    );
     let request = UserAuthenticateRequest::new(credential);
-    let response_result = internal_client.user_authenticate(request);
+    let response_result = internal_client.user_authenticate(request).await;
     debug!("{:?}", response_result);
     assert!(response_result.is_ok());
 }
 
-#[test_case]
-fn test_authenticate_fail() {
-    let mut api_client = get_api_client_with_credential(shared_admin_credential());
-    let mut internal_client = get_internal_client();
+#[async_test_case]
+async fn test_authenticate_fail() {
+    let mut api_client = get_api_client_with_admin_credential().await;
+    let mut internal_client = get_internal_client().await;
 
     let request = UserRegisterRequest::new(
         "test_authenticate_id2",
@@ -158,36 +123,36 @@
         "PlatformAdmin",
         "",
     );
-    let response_result = api_client.user_register(request);
+    let response_result = api_client.user_register(request).await;
     assert!(response_result.is_ok());
 
     let credential = UserCredential::new("test_authenticate_id2", "wrong_token");
     let request = UserAuthenticateRequest::new(credential);
-    let response_result = internal_client.user_authenticate(request);
+    let response_result = internal_client.user_authenticate(request).await;
     debug!("{:?}", response_result);
     assert!(response_result.is_err());
 }
 
-#[test_case]
-fn test_register_success() {
-    let mut client = get_api_client_with_credential(shared_admin_credential());
+#[async_test_case]
+async fn test_register_success() {
+    let mut client = get_api_client_with_admin_credential().await;
     let request =
         UserRegisterRequest::new("test_register_id1", "test_password", "PlatformAdmin", "");
-    let response_result = client.user_register(request);
+    let response_result = client.user_register(request).await;
     debug!("{:?}", response_result);
     assert!(response_result.is_ok());
 }
 
-#[test_case]
-fn test_register_fail() {
-    let mut client = get_api_client_with_credential(shared_admin_credential());
+#[async_test_case]
+async fn test_register_fail() {
+    let mut client = get_api_client_with_admin_credential().await;
     let request =
         UserRegisterRequest::new("test_register_id2", "test_password", "PlatformAdmin", "");
-    let response_result = client.user_register(request);
+    let response_result = client.user_register(request).await;
     assert!(response_result.is_ok());
     let request =
         UserRegisterRequest::new("test_register_id2", "test_password", "PlatformAdmin", "");
-    let response_result = client.user_register(request);
+    let response_result = client.user_register(request).await;
     debug!("{:?}", response_result);
     assert!(response_result.is_err());
 }
diff --git a/tests/functional/enclave/src/end_to_end/builtin_echo.rs b/tests/functional/enclave/src/end_to_end/builtin_echo.rs
index 3b1da0c..b86f05f 100644
--- a/tests/functional/enclave/src/end_to_end/builtin_echo.rs
+++ b/tests/functional/enclave/src/end_to_end/builtin_echo.rs
@@ -16,16 +16,20 @@
 // under the License.
 
 use super::*;
-use teaclave_test_utils::test_case;
-
-#[test_case]
-pub fn test_echo_task_success() {
+use futures::FutureExt;
+use teaclave_test_utils::async_test_case;
+#[async_test_case]
+pub async fn test_echo_task_success() {
     // Authenticate user before talking to frontend service
-    let mut api_client =
-        create_authentication_api_client(shared_enclave_info(), AUTH_SERVICE_ADDR).unwrap();
-    let cred = login(&mut api_client, USERNAME, TEST_PASSWORD).unwrap();
-    let mut client =
-        create_frontend_client(shared_enclave_info(), FRONTEND_SERVICE_ADDR, cred).unwrap();
+    let mut api_client = create_authentication_api_client(shared_enclave_info(), AUTH_SERVICE_ADDR)
+        .await
+        .unwrap();
+    let cred = login(&mut api_client, USERNAME, TEST_PASSWORD)
+        .await
+        .unwrap();
+    let mut client = create_frontend_client(shared_enclave_info(), FRONTEND_SERVICE_ADDR, cred)
+        .await
+        .unwrap();
     let arg = FunctionArgument::new("message", "", true);
 
     // Register Function
@@ -35,22 +39,26 @@
         .arguments(vec![arg])
         .build();
 
-    let response = client.register_function(request).unwrap();
+    let response = client
+        .register_function(request)
+        .await
+        .unwrap()
+        .into_inner();
 
     log::debug!("Register function: {:?}", response);
 
     // Create Task
-    let function_id = response.function_id;
+    let function_id = response.function_id.try_into().unwrap();
     let request = CreateTaskRequest::new()
         .function_id(function_id)
         .function_arguments(hashmap!("message" => "Hello From Teaclave!"))
         .executor(Executor::Builtin);
 
-    let response = client.create_task(request).unwrap();
+    let response = client.create_task(request).await.unwrap().into_inner();
 
     log::debug!("Create task: {:?}", response);
 
-    let task_id = response.task_id;
+    let task_id = response.task_id.try_into().unwrap();
 
     // Assign Data To Task
     // This task does not have any input/output files, we can opt to skip the assignment process.
@@ -60,9 +68,9 @@
     // approve_task(&mut client, &task_id).unwrap();
 
     // Invoke Task
-    invoke_task(&mut client, &task_id).unwrap();
+    invoke_task(&mut client, &task_id).await.unwrap();
 
     // Get Task
-    let ret_val = get_task_until(&mut client, &task_id, TaskStatus::Finished);
+    let ret_val = get_task_until(&mut client, &task_id, TaskStatus::Finished).await;
     assert_eq!(&ret_val, "Hello From Teaclave!");
 }
diff --git a/tests/functional/enclave/src/end_to_end/builtin_gbdt_train.rs b/tests/functional/enclave/src/end_to_end/builtin_gbdt_train.rs
index 2672a85..1707def 100644
--- a/tests/functional/enclave/src/end_to_end/builtin_gbdt_train.rs
+++ b/tests/functional/enclave/src/end_to_end/builtin_gbdt_train.rs
@@ -16,36 +16,44 @@
 // under the License.
 
 use super::*;
+use futures::FutureExt;
 use teaclave_crypto::TeaclaveFile128Key;
-use teaclave_test_utils::test_case;
-
-#[test_case]
-pub fn test_gbdt_training_task() {
-    let mut client = authorized_frontend_client();
-    let function_id = register_gbdt_function(&mut client);
-    let training_data_id = register_input_file(&mut client);
+use teaclave_rpc::CredentialService;
+use teaclave_test_utils::async_test_case;
+#[async_test_case]
+pub async fn test_gbdt_training_task() {
+    let mut client = authorized_frontend_client().await;
+    let function_id = register_gbdt_function(&mut client).await;
+    let training_data_id = register_input_file(&mut client).await;
 
     let crypto = TeaclaveFile128Key::random();
-    let output_model_id = register_output_file(&mut client, crypto);
+    let output_model_id = register_output_file(&mut client, crypto).await;
 
-    let task_id = create_gbdt_training_task(&mut client, &function_id);
-    assign_data_to_task(&mut client, &task_id, training_data_id, output_model_id);
-    approve_task(&mut client, &task_id).unwrap();
-    invoke_task(&mut client, &task_id).unwrap();
+    let task_id = create_gbdt_training_task(&mut client, &function_id).await;
+    assign_data_to_task(&mut client, &task_id, training_data_id, output_model_id).await;
+    approve_task(&mut client, &task_id).await.unwrap();
+    invoke_task(&mut client, &task_id).await.unwrap();
 
-    let ret_val = get_task_until(&mut client, &task_id, TaskStatus::Finished);
+    let ret_val = get_task_until(&mut client, &task_id, TaskStatus::Finished).await;
     assert_eq!(&ret_val, "Trained 120 lines of data.");
 }
 
 // Authenticate user before talking to frontend service
-fn authorized_frontend_client() -> TeaclaveFrontendClient {
-    let mut api_client =
-        create_authentication_api_client(shared_enclave_info(), AUTH_SERVICE_ADDR).unwrap();
-    let cred = login(&mut api_client, USERNAME, TEST_PASSWORD).unwrap();
-    create_frontend_client(shared_enclave_info(), FRONTEND_SERVICE_ADDR, cred).unwrap()
+async fn authorized_frontend_client() -> TeaclaveFrontendClient<CredentialService> {
+    let mut api_client = create_authentication_api_client(shared_enclave_info(), AUTH_SERVICE_ADDR)
+        .await
+        .unwrap();
+    let cred = login(&mut api_client, USERNAME, TEST_PASSWORD)
+        .await
+        .unwrap();
+    create_frontend_client(shared_enclave_info(), FRONTEND_SERVICE_ADDR, cred)
+        .await
+        .unwrap()
 }
 
-fn register_gbdt_function(client: &mut TeaclaveFrontendClient) -> ExternalID {
+async fn register_gbdt_function(
+    client: &mut TeaclaveFrontendClient<CredentialService>,
+) -> ExternalID {
     let fn_input = FunctionInput::new("training_data", "Input traning data file.", false);
     let fn_output = FunctionOutput::new("trained_model", "Output trained model.", false);
     let fn_args = vec![
@@ -68,13 +76,16 @@
         .inputs(vec![fn_input])
         .outputs(vec![fn_output])
         .build();
-
-    let response = client.register_function(request).unwrap();
+    let response = client
+        .register_function(request)
+        .await
+        .unwrap()
+        .into_inner();
     log::debug!("Register function: {:?}", response);
-    response.function_id
+    response.function_id.try_into().unwrap()
 }
 
-fn register_input_file(client: &mut TeaclaveFrontendClient) -> ExternalID {
+async fn register_input_file(client: &mut TeaclaveFrontendClient<CredentialService>) -> ExternalID {
     let url =
         Url::parse("http://localhost:6789/fixtures/functions/gbdt_training/train.enc").unwrap();
     let crypto = TeaclaveFile128Key::new(&[0; 16]).unwrap();
@@ -82,26 +93,34 @@
     let cmac = FileAuthTag::from_hex("860030495909b84864b991865e9ad94f").unwrap();
 
     let request = RegisterInputFileRequest::new(url, cmac, crypto_info);
-    let response = client.register_input_file(request).unwrap();
+    let response = client
+        .register_input_file(request)
+        .await
+        .unwrap()
+        .into_inner();
     log::debug!("Register input: {:?}", response);
-    response.data_id
+    response.data_id.try_into().unwrap()
 }
 
-fn register_output_file(
-    client: &mut TeaclaveFrontendClient,
+async fn register_output_file(
+    client: &mut TeaclaveFrontendClient<CredentialService>,
     crypto: impl Into<FileCrypto>,
 ) -> ExternalID {
     let url =
         Url::parse("http://localhost:6789/fixtures/functions/gbdt_training/e2e_output_model.enc")
             .unwrap();
     let request = RegisterOutputFileRequest::new(url, crypto);
-    let response = client.register_output_file(request).unwrap();
+    let response = client
+        .register_output_file(request)
+        .await
+        .unwrap()
+        .into_inner();
     log::debug!("Register output: {:?}", response);
-    response.data_id
+    response.data_id.try_into().unwrap()
 }
 
-fn create_gbdt_training_task(
-    client: &mut TeaclaveFrontendClient,
+async fn create_gbdt_training_task(
+    client: &mut TeaclaveFrontendClient<CredentialService>,
     function_id: &ExternalID,
 ) -> ExternalID {
     let arguments = FunctionArguments::from_json(serde_json::json!({
@@ -123,14 +142,14 @@
         .inputs_ownership(hashmap!("training_data" => vec![USERNAME]))
         .outputs_ownership(hashmap!("trained_model" => vec![USERNAME]));
 
-    let response = client.create_task(request).unwrap();
+    let response = client.create_task(request).await.unwrap().into_inner();
     log::debug!("Create task: {:?}", response);
 
-    response.task_id
+    response.task_id.try_into().unwrap()
 }
 
-fn assign_data_to_task(
-    client: &mut TeaclaveFrontendClient,
+async fn assign_data_to_task(
+    client: &mut TeaclaveFrontendClient<CredentialService>,
     task_id: &ExternalID,
     training_data_id: ExternalID,
     out_model_id: ExternalID,
@@ -141,7 +160,7 @@
         hashmap!("training_data" => training_data_id),
         hashmap!("trained_model" => out_model_id),
     );
-    let response = client.assign_data(request).unwrap();
+    let response = client.assign_data(request).await.unwrap();
 
     log::debug!("Assign data: {:?}", response);
 }
diff --git a/tests/functional/enclave/src/end_to_end/mesapy_data_fusion.rs b/tests/functional/enclave/src/end_to_end/mesapy_data_fusion.rs
index d2f992d..753d998 100644
--- a/tests/functional/enclave/src/end_to_end/mesapy_data_fusion.rs
+++ b/tests/functional/enclave/src/end_to_end/mesapy_data_fusion.rs
@@ -16,22 +16,27 @@
 // under the License.
 
 use super::*;
+use futures::FutureExt;
 use std::collections::HashMap;
 use teaclave_crypto::{AesGcm128Key, AesGcm256Key};
-use teaclave_test_utils::test_case;
+use teaclave_rpc::CredentialService;
+use teaclave_test_utils::async_test_case;
+type FrontendClient = TeaclaveFrontendClient<CredentialService>;
 
-fn setup_client() -> anyhow::Result<(TeaclaveFrontendClient, TeaclaveFrontendClient)> {
+async fn setup_client() -> anyhow::Result<(FrontendClient, FrontendClient)> {
     // Authenticate user before talking to frontend service
     let mut api_client =
-        create_authentication_api_client(shared_enclave_info(), AUTH_SERVICE_ADDR)?;
-    let cred = login(&mut api_client, USERNAME1, TEST_PASSWORD)?;
-    let client1 = create_frontend_client(shared_enclave_info(), FRONTEND_SERVICE_ADDR, cred)?;
-    let cred = login(&mut api_client, USERNAME2, TEST_PASSWORD)?;
-    let client2 = create_frontend_client(shared_enclave_info(), FRONTEND_SERVICE_ADDR, cred)?;
+        create_authentication_api_client(shared_enclave_info(), AUTH_SERVICE_ADDR).await?;
+    let cred = login(&mut api_client, USERNAME1, TEST_PASSWORD).await?;
+    let client1 =
+        create_frontend_client(shared_enclave_info(), FRONTEND_SERVICE_ADDR, cred).await?;
+    let cred = login(&mut api_client, USERNAME2, TEST_PASSWORD).await?;
+    let client2 =
+        create_frontend_client(shared_enclave_info(), FRONTEND_SERVICE_ADDR, cred).await?;
     Ok((client1, client2))
 }
 
-fn register_data_fusion_function(client: &mut TeaclaveFrontendClient) -> ExternalID {
+async fn register_data_fusion_function(client: &mut FrontendClient) -> ExternalID {
     let script = r#"
 def readlines(fid):
     lines = None
@@ -64,13 +69,18 @@
         .inputs(vec![input1, input2])
         .outputs(vec![fusion_output])
         .build();
-    let response = client.register_function(request).unwrap();
+    let response = client
+        .register_function(request)
+        .await
+        .unwrap()
+        .into_inner();
+
     log::debug!("Resgister function: {:?}", response);
-    response.function_id
+    response.function_id.try_into().unwrap()
 }
 
-fn register_input_file(
-    client: &mut TeaclaveFrontendClient,
+async fn register_input_file(
+    client: &mut FrontendClient,
     url: impl AsRef<str>,
     crypto: impl Into<FileCrypto>,
     auth_tag: impl AsRef<str>,
@@ -78,22 +88,30 @@
     let url = Url::parse(url.as_ref()).unwrap();
     let cmac = FileAuthTag::from_hex(auth_tag.as_ref()).unwrap();
     let request = RegisterInputFileRequest::new(url, cmac, crypto);
-    let response = client.register_input_file(request).unwrap();
+    let response = client
+        .register_input_file(request)
+        .await
+        .unwrap()
+        .into_inner();
     log::debug!("Register input: {:?}", response);
-    response.data_id
+    response.data_id.try_into().unwrap()
 }
 
-fn register_fusion_output(
-    client: &mut TeaclaveFrontendClient,
+async fn register_fusion_output(
+    client: &mut FrontendClient,
     file_owners: impl Into<OwnerList>,
 ) -> ExternalID {
     let request = RegisterFusionOutputRequest::new(file_owners);
-    let response = client.register_fusion_output(request).unwrap();
-    response.data_id
+    let response = client
+        .register_fusion_output(request)
+        .await
+        .unwrap()
+        .into_inner();
+    response.data_id.try_into().unwrap()
 }
 
-fn create_data_fusion_task(
-    client: &mut TeaclaveFrontendClient,
+async fn create_data_fusion_task(
+    client: &mut FrontendClient,
     function_id: &ExternalID,
 ) -> ExternalID {
     let request = CreateTaskRequest::new()
@@ -104,30 +122,30 @@
         ))
         .outputs_ownership(hashmap!("OutFusionData" => vec![USERNAME1, USERNAME2]))
         .executor(Executor::MesaPy);
-    let response = client.create_task(request).unwrap();
+    let response = client.create_task(request).await.unwrap().into_inner();
     log::debug!("Create task: {:?}", response);
-    response.task_id
+    response.task_id.try_into().unwrap()
 }
 
-fn assign_data_for_task(
-    client: &mut TeaclaveFrontendClient,
+async fn assign_data_for_task(
+    client: &mut FrontendClient,
     task_id: &ExternalID,
     input_map: HashMap<String, ExternalID>,
     output_map: HashMap<String, ExternalID>,
 ) {
     let request = AssignDataRequest::new(task_id.clone(), input_map, output_map);
-    let response = client.assign_data(request).unwrap();
+    let response = client.assign_data(request).await.unwrap();
     log::debug!("Assign data: {:?}", response);
 }
 
-#[test_case]
-pub fn test_data_fusion_success() {
-    let (mut c1, mut c2) = setup_client().unwrap();
+#[async_test_case]
+pub async fn test_data_fusion_success() {
+    let (mut c1, mut c2) = setup_client().await.unwrap();
 
-    let function_id = register_data_fusion_function(&mut c1);
+    let function_id = register_data_fusion_function(&mut c1).await;
 
     // Create Task
-    let task_id = create_data_fusion_task(&mut c1, &function_id);
+    let task_id = create_data_fusion_task(&mut c1, &function_id).await;
 
     // Register Data and Assign Data To Task
     // input1 is owned by user1
@@ -136,17 +154,18 @@
     let iv = "123456781234567812345678";
     let cmac = "e8afd048b339fc835733e16c761a301c";
     let crypto = AesGcm128Key::from_hex(key, iv).unwrap();
-    let input1 = register_input_file(&mut c1, path, crypto, cmac);
+    let input1 = register_input_file(&mut c1, path, crypto, cmac).await;
 
     // fusion_output is owned by user1 and user2
-    let fusion_output = register_fusion_output(&mut c1, vec![USERNAME1, USERNAME2]);
+    let fusion_output = register_fusion_output(&mut c1, vec![USERNAME1, USERNAME2]).await;
 
     assign_data_for_task(
         &mut c1,
         &task_id,
         hashmap!("InPartyA" => input1),
         hashmap!("OutFusionData" => fusion_output),
-    );
+    )
+    .await;
 
     // input2 is owned by user2
     let path = "http://localhost:6789/fixtures/fusion/input2.enc";
@@ -154,63 +173,71 @@
     let iv = "012345670123456701234567";
     let cmac = "75d7cf7a7843dee709e29ba0dcb865d2";
     let crypto = AesGcm256Key::from_hex(key, iv).unwrap();
-    let input2 = register_input_file(&mut c2, path, crypto, cmac);
+    let input2 = register_input_file(&mut c2, path, crypto, cmac).await;
     assign_data_for_task(
         &mut c2,
         &task_id,
         hashmap!("InPartyB" => input2),
         hashmap!(),
-    );
+    )
+    .await;
 
     // Approve Task
-    approve_task(&mut c1, &task_id).unwrap();
-    approve_task(&mut c2, &task_id).unwrap();
+    approve_task(&mut c1, &task_id).await.unwrap();
+    approve_task(&mut c2, &task_id).await.unwrap();
 
     // Invoke Task by the creator
-    invoke_task(&mut c1, &task_id).unwrap();
+    invoke_task(&mut c1, &task_id).await.unwrap();
 
     // Get Task
-    let ret_val = get_task_until(&mut c1, &task_id, TaskStatus::Finished);
+    let ret_val = get_task_until(&mut c1, &task_id, TaskStatus::Finished).await;
     assert_eq!(&ret_val, "Mixed 5 lines of data");
 
-    let task = get_task(&mut c2, &task_id);
-    assert!(task.status == TaskStatus::Finished);
+    let task = get_task(&mut c2, &task_id).await;
+    assert!(task.status == i32_from_task_status(TaskStatus::Finished));
 
-    let fusion_id = task.assigned_outputs.get("OutFusionData").unwrap();
-    let fusion_owners = task.outputs_ownership.get("OutFusionData").unwrap();
+    let outputs = from_proto_file_ids(task.assigned_outputs).unwrap();
+    let fusion_id = outputs.get("OutFusionData").unwrap();
+    let owners = from_proto_ownership(task.outputs_ownership);
+    let fusion_owners = owners.get("OutFusionData").unwrap();
 
-    let fusion_input = register_fusion_input_from_output(&mut c2, fusion_id);
-    let function_id = register_word_count_function(&mut c2);
+    let fusion_input = register_fusion_input_from_output(&mut c2, fusion_id).await;
+    let function_id = register_word_count_function(&mut c2).await;
 
-    let task_id = create_wlc_task(&mut c2, &function_id, fusion_owners);
+    let task_id = create_wlc_task(&mut c2, &function_id, fusion_owners).await;
     assign_data_for_task(
         &mut c2,
         &task_id,
         hashmap!("InputData" => fusion_input),
         hashmap!(),
-    );
+    )
+    .await;
 
-    approve_task(&mut c2, &task_id).unwrap();
+    approve_task(&mut c2, &task_id).await.unwrap();
 
     // Invoke Task by the creator
-    assert!(invoke_task(&mut c2, &task_id).is_err());
+    assert!(invoke_task(&mut c2, &task_id).await.is_err());
 
-    approve_task(&mut c1, &task_id).unwrap();
-    invoke_task(&mut c2, &task_id).unwrap();
-    let ret_val = get_task_until(&mut c2, &task_id, TaskStatus::Finished);
+    approve_task(&mut c1, &task_id).await.unwrap();
+    invoke_task(&mut c2, &task_id).await.unwrap();
+    let ret_val = get_task_until(&mut c2, &task_id, TaskStatus::Finished).await;
     assert_eq!(&ret_val, "2");
 }
 
-fn register_fusion_input_from_output(
-    client: &mut TeaclaveFrontendClient,
+async fn register_fusion_input_from_output(
+    client: &mut FrontendClient,
     fusion_id: &ExternalID,
 ) -> ExternalID {
     let request = RegisterInputFromOutputRequest::new(fusion_id.clone());
-    let response = client.register_input_from_output(request).unwrap();
-    response.data_id
+    let response = client
+        .register_input_from_output(request)
+        .await
+        .unwrap()
+        .into_inner();
+    response.data_id.try_into().unwrap()
 }
 
-fn register_word_count_function(client: &mut TeaclaveFrontendClient) -> ExternalID {
+async fn register_word_count_function(client: &mut FrontendClient) -> ExternalID {
     let script = r#"
 def readlines(fid):
     lines = None
@@ -241,13 +268,17 @@
         .public(true)
         .inputs(vec![input_spec])
         .build();
-    let response = client.register_function(request).unwrap();
+    let response = client
+        .register_function(request)
+        .await
+        .unwrap()
+        .into_inner();
     log::debug!("Resgister function: {:?}", response);
-    response.function_id
+    response.function_id.try_into().unwrap()
 }
 
-fn create_wlc_task(
-    client: &mut TeaclaveFrontendClient,
+async fn create_wlc_task(
+    client: &mut FrontendClient,
     function_id: &ExternalID,
     owners: &OwnerList,
 ) -> ExternalID {
@@ -258,7 +289,7 @@
             "InputData" => owners.to_owned()
         ))
         .executor(Executor::MesaPy);
-    let response = client.create_task(request).unwrap();
+    let response = client.create_task(request).await.unwrap().into_inner();
     log::debug!("Create task: {:?}", response);
-    response.task_id
+    response.task_id.try_into().unwrap()
 }
diff --git a/tests/functional/enclave/src/end_to_end/mesapy_echo.rs b/tests/functional/enclave/src/end_to_end/mesapy_echo.rs
index 761f3be..068ef1c 100644
--- a/tests/functional/enclave/src/end_to_end/mesapy_echo.rs
+++ b/tests/functional/enclave/src/end_to_end/mesapy_echo.rs
@@ -16,16 +16,20 @@
 // under the License.
 
 use super::*;
-use teaclave_test_utils::test_case;
-
-#[test_case]
-pub fn test_echo_task_success() {
+use futures::FutureExt;
+use teaclave_test_utils::async_test_case;
+#[async_test_case]
+pub async fn test_echo_task_success() {
     // Authenticate user before talking to frontend service
-    let mut api_client =
-        create_authentication_api_client(shared_enclave_info(), AUTH_SERVICE_ADDR).unwrap();
-    let cred = login(&mut api_client, USERNAME, TEST_PASSWORD).unwrap();
-    let mut client =
-        create_frontend_client(shared_enclave_info(), FRONTEND_SERVICE_ADDR, cred).unwrap();
+    let mut api_client = create_authentication_api_client(shared_enclave_info(), AUTH_SERVICE_ADDR)
+        .await
+        .unwrap();
+    let cred = login(&mut api_client, USERNAME, TEST_PASSWORD)
+        .await
+        .unwrap();
+    let mut client = create_frontend_client(shared_enclave_info(), FRONTEND_SERVICE_ADDR, cred)
+        .await
+        .unwrap();
 
     let script = "
 def entrypoint(argv):
@@ -44,35 +48,37 @@
         .arguments(vec![arg])
         .build();
 
-    let response = client.register_function(request).unwrap();
-
+    let response = client
+        .register_function(request)
+        .await
+        .unwrap()
+        .into_inner();
     log::debug!("Resgister function: {:?}", response);
 
     // Create Task
-    let function_id = response.function_id;
+    let function_id = response.function_id.try_into().unwrap();
     let request = CreateTaskRequest::new()
         .function_id(function_id)
         .function_arguments(hashmap!("message" => "Hello From Teaclave!"))
         .executor(Executor::MesaPy);
 
-    let response = client.create_task(request).unwrap();
-
+    let response = client.create_task(request).await.unwrap().into_inner();
     log::debug!("Create task: {:?}", response);
 
     // Assign Data To Task
-    let task_id = response.task_id;
+    let task_id: ExternalID = response.task_id.try_into().unwrap();
     let request = AssignDataRequest::new(task_id.clone(), hashmap!(), hashmap!());
-    let response = client.assign_data(request).unwrap();
+    let response = client.assign_data(request).await.unwrap();
 
     log::debug!("Assign data: {:?}", response);
 
     // Approve Task
-    approve_task(&mut client, &task_id).unwrap();
+    approve_task(&mut client, &task_id).await.unwrap();
 
     // Invoke Task
-    invoke_task(&mut client, &task_id).unwrap();
+    invoke_task(&mut client, &task_id).await.unwrap();
 
     // Get Task
-    let ret_val = get_task_until(&mut client, &task_id, TaskStatus::Finished);
+    let ret_val = get_task_until(&mut client, &task_id, TaskStatus::Finished).await;
     assert_eq!(&ret_val, "Hello From Teaclave!");
 }
diff --git a/tests/functional/enclave/src/end_to_end/mod.rs b/tests/functional/enclave/src/end_to_end/mod.rs
index 8c91f46..9338371 100644
--- a/tests/functional/enclave/src/end_to_end/mod.rs
+++ b/tests/functional/enclave/src/end_to_end/mod.rs
@@ -16,36 +16,39 @@
 // under the License.
 
 use crate::utils::*;
+use teaclave_proto::teaclave_common::i32_from_task_status;
 use teaclave_proto::teaclave_frontend_service::*;
 use teaclave_types::*;
 use url::Url;
-
 mod builtin_echo;
 mod builtin_gbdt_train;
 mod mesapy_data_fusion;
 mod mesapy_echo;
+use teaclave_rpc::CredentialService;
 
-fn get_task(client: &mut TeaclaveFrontendClient, task_id: &ExternalID) -> GetTaskResponse {
+async fn get_task(
+    client: &mut TeaclaveFrontendClient<CredentialService>,
+    task_id: &ExternalID,
+) -> GetTaskResponse {
     let request = GetTaskRequest::new(task_id.clone());
-    let response = client.get_task(request).unwrap();
+    let response = client.get_task(request).await.unwrap().into_inner();
     log::debug!("Get task: {:?}", response);
     response
 }
 
-fn get_task_until(
-    client: &mut TeaclaveFrontendClient,
+async fn get_task_until(
+    client: &mut TeaclaveFrontendClient<CredentialService>,
     task_id: &ExternalID,
     status: TaskStatus,
 ) -> String {
+    let status = i32_from_task_status(status);
     loop {
-        let request = GetTaskRequest::new(task_id.clone());
-        let response = client.get_task(request).unwrap();
-        log::debug!("Get task: {:?}", response);
-
+        let response = get_task(client, task_id).await;
         std::thread::sleep(std::time::Duration::from_secs(1));
 
         if response.status == status {
-            match response.result {
+            let result = teaclave_types::TaskResult::try_from(response.result).unwrap();
+            match result {
                 TaskResult::Ok(outputs) => {
                     let ret_val = String::from_utf8(outputs.return_value).unwrap();
                     log::debug!("Task returns: {:?}", ret_val);
@@ -61,16 +64,22 @@
     }
 }
 
-fn approve_task(client: &mut TeaclaveFrontendClient, task_id: &ExternalID) -> anyhow::Result<()> {
+async fn approve_task(
+    client: &mut TeaclaveFrontendClient<CredentialService>,
+    task_id: &ExternalID,
+) -> anyhow::Result<()> {
     let request = ApproveTaskRequest::new(task_id.clone());
-    let response = client.approve_task(request)?;
+    let response = client.approve_task(request).await?.into_inner();
     log::debug!("Approve task: {:?}", response);
     Ok(())
 }
 
-fn invoke_task(client: &mut TeaclaveFrontendClient, task_id: &ExternalID) -> anyhow::Result<()> {
+async fn invoke_task(
+    client: &mut TeaclaveFrontendClient<CredentialService>,
+    task_id: &ExternalID,
+) -> anyhow::Result<()> {
     let request = InvokeTaskRequest::new(task_id.clone());
-    let response = client.invoke_task(request)?;
+    let response = client.invoke_task(request).await?.into_inner();
     log::debug!("Invoke task: {:?}", response);
     Ok(())
 }
diff --git a/tests/functional/enclave/src/execution_service.rs b/tests/functional/enclave/src/execution_service.rs
index f645f16..f320ad6 100644
--- a/tests/functional/enclave/src/execution_service.rs
+++ b/tests/functional/enclave/src/execution_service.rs
@@ -16,14 +16,14 @@
 // under the License.
 
 use crate::utils::*;
+use futures::FutureExt;
 use teaclave_proto::teaclave_storage_service::*;
-use teaclave_test_utils::test_case;
+use teaclave_test_utils::async_test_case;
 use teaclave_types::*;
-
 use uuid::Uuid;
 
-#[test_case]
-fn test_execute_function() {
+#[async_test_case]
+async fn test_execute_function() {
     let task_id = Uuid::new_v4();
     let ts = TaskState {
         task_id,
@@ -44,26 +44,25 @@
         ))
         .build();
 
-    let mut storage_client = get_storage_client();
+    let mut storage_client = get_storage_client().await;
     let enqueue_request = EnqueueRequest::new(
         StagedTask::get_queue_key().as_bytes(),
         staged_task.to_vec().unwrap(),
     );
-    let _enqueue_response = storage_client.enqueue(enqueue_request).unwrap();
+    let _enqueue_response = storage_client.enqueue(enqueue_request).await.unwrap();
     let put_request = PutRequest::new(ts.key().as_slice(), ts.to_vec().unwrap().as_slice());
-    let _put_response = storage_client.put(put_request).unwrap();
-
+    let _put_response = storage_client.put(put_request).await.unwrap();
     std::thread::sleep(std::time::Duration::from_secs(15));
 
     let get_request = GetRequest::new(ts.key().as_slice());
-    let get_response = storage_client.get(get_request).unwrap();
+    let get_response = storage_client.get(get_request).await.unwrap().into_inner();
     let updated_task = TaskState::from_slice(get_response.value.as_slice()).unwrap();
     let result = updated_task.result.unwrap();
     assert_eq!(result.return_value, b"Hello, Teaclave Tests!");
-    let info_log = result.log.iter().find(|l| l.contains("INFO")).unwrap();
 
-    assert_eq!(
-        info_log,
-        "[INFO teaclave_function::echo] Hello, Teaclave Tests!"
-    );
+    let info_log = result
+        .log
+        .iter()
+        .find(|l| l.contains("[INFO teaclave_function::echo] Hello, Teaclave Tests!"));
+    assert!(info_log.is_some())
 }
diff --git a/tests/functional/enclave/src/frontend_service.rs b/tests/functional/enclave/src/frontend_service.rs
index 2ae4abe..e495d9d 100644
--- a/tests/functional/enclave/src/frontend_service.rs
+++ b/tests/functional/enclave/src/frontend_service.rs
@@ -16,182 +16,219 @@
 // under the License.
 
 use crate::utils::*;
+use futures::FutureExt;
 use std::convert::TryFrom;
 use teaclave_proto::teaclave_common::*;
 use teaclave_proto::teaclave_common::{ExecutorCommand, ExecutorStatus};
 use teaclave_proto::teaclave_frontend_service::*;
 use teaclave_proto::teaclave_scheduler_service::*;
-use teaclave_test_utils::test_case;
+use teaclave_rpc::CredentialService;
+use teaclave_test_utils::async_test_case;
 use teaclave_types::*;
 use url::Url;
 use uuid::Uuid;
 
-fn authorized_client() -> TeaclaveFrontendClient {
-    let mut api_client =
-        create_authentication_api_client(shared_enclave_info(), AUTH_SERVICE_ADDR).unwrap();
-    let cred = login(&mut api_client, USERNAME, TEST_PASSWORD).unwrap();
-    create_frontend_client(shared_enclave_info(), FRONTEND_SERVICE_ADDR, cred).unwrap()
+async fn authorized_client() -> TeaclaveFrontendClient<CredentialService> {
+    let mut api_client = create_authentication_api_client(shared_enclave_info(), AUTH_SERVICE_ADDR)
+        .await
+        .unwrap();
+    let cred = login(&mut api_client, USERNAME, TEST_PASSWORD)
+        .await
+        .unwrap();
+    create_frontend_client(shared_enclave_info(), FRONTEND_SERVICE_ADDR, cred)
+        .await
+        .unwrap()
 }
 
-fn unauthorized_client() -> TeaclaveFrontendClient {
+async fn unauthorized_client() -> TeaclaveFrontendClient<CredentialService> {
     let cred = UserCredential::new(USERNAME, "InvalidToken");
-    create_frontend_client(shared_enclave_info(), FRONTEND_SERVICE_ADDR, cred).unwrap()
+    create_frontend_client(shared_enclave_info(), FRONTEND_SERVICE_ADDR, cred)
+        .await
+        .unwrap()
 }
 
-#[test_case]
-fn test_register_input_file() {
+#[async_test_case]
+async fn test_register_input_file() {
     let url = Url::parse("https://external-storage.com/filepath?presigned_token").unwrap();
     let cmac = FileAuthTag::mock();
     let crypto_info = FileCrypto::default();
 
     let request = RegisterInputFileRequest::new(url.clone(), cmac, crypto_info);
-    let response = authorized_client().register_input_file(request);
+    let mut client = authorized_client().await;
+    let response = client.register_input_file(request).await;
     assert!(response.is_ok());
 
     let request = RegisterInputFileRequest::new(url, cmac, crypto_info);
-    let response = unauthorized_client().register_input_file(request);
+    let mut client = unauthorized_client().await;
+    let response = client.register_input_file(request).await;
     assert!(response.is_err());
 }
 
-#[test_case]
-fn test_update_input_file() {
+#[async_test_case]
+async fn test_update_input_file() {
     let url = Url::parse("https://external-storage.com/filepath?presigned_token").unwrap();
     let cmac = FileAuthTag::mock();
     let crypto_info = FileCrypto::default();
 
     let request = RegisterInputFileRequest::new(url, cmac, crypto_info);
-    let response = authorized_client().register_input_file(request);
+    let mut client = authorized_client().await;
+    let response = client.register_input_file(request).await;
     assert!(response.is_ok());
 
-    let old_data_id = response.unwrap().data_id;
+    let old_data_id = response.unwrap().into_inner().data_id;
     let new_url = Url::parse("https://external-storage.com/filepath-new?presigned_token").unwrap();
-    let update_request = UpdateInputFileRequest::new(old_data_id.clone(), new_url);
-    let update_response = authorized_client().update_input_file(update_request);
+    let update_request =
+        UpdateInputFileRequest::new(old_data_id.clone().try_into().unwrap(), new_url);
+    let mut client = authorized_client().await;
+    let update_response = client.update_input_file(update_request).await;
     assert!(update_response.is_ok());
-    assert!(old_data_id != update_response.unwrap().data_id);
+    assert!(old_data_id != update_response.unwrap().into_inner().data_id);
 }
 
-#[test_case]
-fn test_register_output_file() {
+#[async_test_case]
+async fn test_register_output_file() {
     let url = Url::parse("https://external-storage.com/filepath?presigned_token").unwrap();
     let crypto_info = FileCrypto::default();
 
     let request = RegisterOutputFileRequest::new(url.clone(), crypto_info);
-    let response = authorized_client().register_output_file(request);
+    let mut client = authorized_client().await;
+    let response = client.register_output_file(request).await;
     assert!(response.is_ok());
 
     let request = RegisterOutputFileRequest::new(url, crypto_info);
-    let response = unauthorized_client().register_output_file(request);
+    let mut client = unauthorized_client().await;
+    let response = client.register_output_file(request).await;
     assert!(response.is_err());
 }
 
-#[test_case]
-fn test_update_output_file() {
+#[async_test_case]
+async fn test_update_output_file() {
     let url = Url::parse("https://external-storage.com/filepath?presigned_token").unwrap();
     let crypto_info = FileCrypto::default();
 
     let request = RegisterOutputFileRequest::new(url, crypto_info);
-    let response = authorized_client().register_output_file(request);
+    let mut client = authorized_client().await;
+    let response = client.register_output_file(request).await;
     assert!(response.is_ok());
 
-    let old_data_id = response.unwrap().data_id;
+    let old_data_id = response.unwrap().into_inner().data_id;
     let new_url = Url::parse("https://external-storage.com/filepath-new?presigned_token").unwrap();
-    let update_request = UpdateOutputFileRequest::new(old_data_id.clone(), new_url);
-    let update_response = authorized_client().update_output_file(update_request);
+    let update_request =
+        UpdateOutputFileRequest::new(old_data_id.clone().try_into().unwrap(), new_url);
+    let mut client = authorized_client().await;
+    let update_response = client.update_output_file(update_request).await;
     assert!(update_response.is_ok());
-    assert!(old_data_id != update_response.unwrap().data_id);
+    assert!(old_data_id != update_response.unwrap().into_inner().data_id);
 }
 
-#[test_case]
-fn test_register_fusion_output() {
+#[async_test_case]
+async fn test_register_fusion_output() {
     let request = RegisterFusionOutputRequest::new(vec!["frontend_user", "mock_user"]);
-    let response = authorized_client().register_fusion_output(request);
+    let mut client = authorized_client().await;
+    let response = client.register_fusion_output(request).await;
     assert!(response.is_ok());
 
     let request = RegisterFusionOutputRequest::new(vec!["frontend_user", "mock_user"]);
-    let response = unauthorized_client().register_fusion_output(request);
+    let mut client = unauthorized_client().await;
+    let response = client.register_fusion_output(request).await;
     assert!(response.is_err());
 }
 
-#[test_case]
-fn test_register_input_from_output() {
+#[async_test_case]
+async fn test_register_input_from_output() {
     let output_id = ExternalID::try_from("output-00000000-0000-0000-0000-000000000001").unwrap();
 
     let request = RegisterInputFromOutputRequest::new(output_id.clone());
-    let response = authorized_client().register_input_from_output(request);
+    let mut client = authorized_client().await;
+    let response = client.register_input_from_output(request).await;
     assert!(response.is_ok());
 
     let request = RegisterInputFromOutputRequest::new(output_id);
-    let response = unauthorized_client().register_input_from_output(request);
+    let mut client = unauthorized_client().await;
+    let response = client.register_input_from_output(request).await;
     assert!(response.is_err());
 }
 
-#[test_case]
-fn test_get_output_file() {
-    let mut client = authorized_client();
+#[async_test_case]
+async fn test_get_output_file() {
+    let mut client = authorized_client().await;
 
     let url = Url::parse("https://external-storage.com/filepath?presigned_token").unwrap();
     let crypto_info = FileCrypto::default();
 
     let request = RegisterOutputFileRequest::new(url, crypto_info);
-    let response = client.register_output_file(request).unwrap();
-    let data_id = response.data_id;
+    let response = client
+        .register_output_file(request)
+        .await
+        .unwrap()
+        .into_inner();
+    let data_id: ExternalID = response.data_id.try_into().unwrap();
 
     let request = GetOutputFileRequest::new(data_id.clone());
-    client.get_output_file(request).unwrap();
+    client.get_output_file(request).await.unwrap();
 
     let request = GetOutputFileRequest::new(data_id);
-    let response = unauthorized_client().get_output_file(request);
+    let mut client = unauthorized_client().await;
+    let response = client.get_output_file(request).await;
     assert!(response.is_err());
 }
 
-#[test_case]
-fn test_get_input_file() {
-    let mut client = authorized_client();
+#[async_test_case]
+async fn test_get_input_file() {
+    let mut client = authorized_client().await;
 
     let url = Url::parse("https://external-storage.com/filepath?presigned_token").unwrap();
     let cmac = FileAuthTag::mock();
     let crypto_info = FileCrypto::default();
 
     let request = RegisterInputFileRequest::new(url, cmac, crypto_info);
-    let response = client.register_input_file(request).unwrap();
-    let data_id = response.data_id;
+    let response = client
+        .register_input_file(request)
+        .await
+        .unwrap()
+        .into_inner();
+    let data_id: ExternalID = response.data_id.try_into().unwrap();
 
     let request = GetInputFileRequest::new(data_id.clone());
-    client.get_input_file(request).unwrap();
+    client.get_input_file(request).await.unwrap();
 
     let request = GetInputFileRequest::new(data_id);
-    let response = unauthorized_client().get_input_file(request);
+    let mut client = unauthorized_client().await;
+    let response = client.get_input_file(request).await;
     assert!(response.is_err());
 }
 
-#[test_case]
-fn test_register_function() {
-    let request = RegisterFunctionRequest::default();
-    let response = authorized_client().register_function(request);
+#[async_test_case]
+async fn test_register_function() {
+    let request = RegisterFunctionRequestBuilder::new().build();
+    let mut client = authorized_client().await;
+    let response = client.register_function(request).await;
     assert!(response.is_ok());
 
-    let request = RegisterFunctionRequest::default();
-    let response = unauthorized_client().register_function(request);
+    let request = RegisterFunctionRequestBuilder::new().build();
+    let mut client = unauthorized_client().await;
+    let response = client.register_function(request).await;
     assert!(response.is_err());
 }
 
-#[test_case]
-fn test_get_function() {
+#[async_test_case]
+async fn test_get_function() {
     let function_id =
         ExternalID::try_from("function-00000000-0000-0000-0000-000000000001").unwrap();
 
     let request = GetFunctionRequest::new(function_id.clone());
-    let response = authorized_client().get_function(request);
+    let mut client = authorized_client().await;
+    let response = client.get_function(request).await;
     assert!(response.is_ok());
 
     let request = GetFunctionRequest::new(function_id);
-    let response = unauthorized_client().get_function(request);
+    let mut client = unauthorized_client().await;
+    let response = client.get_function(request).await;
     assert!(response.is_err());
 }
 
-#[test_case]
-fn test_create_task() {
+#[async_test_case]
+async fn test_create_task() {
     let function_id =
         ExternalID::try_from("function-00000000-0000-0000-0000-000000000002").unwrap();
 
@@ -200,7 +237,8 @@
         .function_arguments(hashmap!("arg1" => "arg1_value"))
         .executor(Executor::MesaPy)
         .outputs_ownership(hashmap!("output" =>  vec!["frontend_user", "mock_user"]));
-    let response = authorized_client().create_task(request);
+    let mut client = authorized_client().await;
+    let response = client.create_task(request).await;
     assert!(response.is_ok());
 
     let request = CreateTaskRequest::new()
@@ -208,13 +246,14 @@
         .function_arguments(hashmap!("arg1" => "arg1_value"))
         .executor(Executor::MesaPy)
         .outputs_ownership(hashmap!("output" => vec!["frontend_user", "mock_user"]));
-    let response = unauthorized_client().create_task(request);
+    let mut client = unauthorized_client().await;
+    let response = client.create_task(request).await;
     assert!(response.is_err());
 }
 
-#[test_case]
-fn test_get_task() {
-    let mut client = authorized_client();
+#[async_test_case]
+async fn test_get_task() {
+    let mut client = authorized_client().await;
     let function_id =
         ExternalID::try_from("function-00000000-0000-0000-0000-000000000002").unwrap();
 
@@ -223,21 +262,21 @@
         .function_arguments(hashmap!("arg1" => "arg1_value"))
         .executor(Executor::MesaPy)
         .outputs_ownership(hashmap!("output" => vec!["frontend_user", "mock_user"]));
-    let response = client.create_task(request).unwrap();
-    let task_id = response.task_id;
-
+    let response = client.create_task(request).await.unwrap().into_inner();
+    let task_id: ExternalID = response.task_id.try_into().unwrap();
     let request = GetTaskRequest::new(task_id.clone());
-    let response = client.get_task(request);
+    let response = client.get_task(request).await;
     assert!(response.is_ok());
 
     let request = GetTaskRequest::new(task_id);
-    let response = unauthorized_client().get_task(request);
+    let mut client = unauthorized_client().await;
+    let response = client.get_task(request).await;
     assert!(response.is_err());
 }
 
-#[test_case]
-fn test_assign_data() {
-    let mut client = authorized_client();
+#[async_test_case]
+async fn test_assign_data() {
+    let mut client = authorized_client().await;
     let function_id =
         ExternalID::try_from("function-00000000-0000-0000-0000-000000000002").unwrap();
     let external_outfile_url =
@@ -250,29 +289,34 @@
         .executor(Executor::MesaPy)
         .outputs_ownership(hashmap!("output" => vec!["frontend_user"]));
 
-    let response = client.create_task(request).unwrap();
-    let task_id = response.task_id;
+    let response = client.create_task(request).await.unwrap().into_inner();
+    let task_id: ExternalID = response.task_id.try_into().unwrap();
 
     let request = RegisterOutputFileRequest::new(external_outfile_url, external_outfile_crypto);
-    let response = client.register_output_file(request).unwrap();
-    let output_id = response.data_id;
+    let response = client
+        .register_output_file(request)
+        .await
+        .unwrap()
+        .into_inner();
+    let output_id: ExternalID = response.data_id.try_into().unwrap();
 
     let request = AssignDataRequest::new(
         task_id.clone(),
         hashmap!(),
         hashmap!("output" => output_id.clone()),
     );
-    let response = unauthorized_client().assign_data(request);
+    let mut unauthorized_client = unauthorized_client().await;
+    let response = unauthorized_client.assign_data(request).await;
     assert!(response.is_err());
 
     let request = AssignDataRequest::new(task_id, hashmap!(), hashmap!("output" => output_id));
-    let response = client.assign_data(request);
+    let response = client.assign_data(request).await;
     assert!(response.is_ok());
 }
 
-#[test_case]
-fn test_approve_task() {
-    let mut client = authorized_client();
+#[async_test_case]
+async fn test_approve_task() {
+    let mut client = authorized_client().await;
     let function_id =
         ExternalID::try_from("function-00000000-0000-0000-0000-000000000002").unwrap();
     let external_outfile_url =
@@ -284,29 +328,34 @@
         .function_arguments(hashmap!("arg1" => "arg1_value"))
         .executor(Executor::MesaPy)
         .outputs_ownership(hashmap!("output" => vec!["frontend_user"]));
-    let response = client.create_task(request).unwrap();
-    let task_id = response.task_id;
+    let response = client.create_task(request).await.unwrap().into_inner();
+    let task_id: ExternalID = response.task_id.try_into().unwrap();
 
     let request = RegisterOutputFileRequest::new(external_outfile_url, external_outfile_crypto);
-    let response = client.register_output_file(request).unwrap();
-    let output_id = response.data_id;
+    let response = client
+        .register_output_file(request)
+        .await
+        .unwrap()
+        .into_inner();
+    let output_id: ExternalID = response.data_id.try_into().unwrap();
 
     let request =
         AssignDataRequest::new(task_id.clone(), hashmap!(), hashmap!("output" => output_id));
-    client.assign_data(request).unwrap();
+    client.assign_data(request).await.unwrap();
 
     let request = ApproveTaskRequest::new(task_id.clone());
-    let response = unauthorized_client().approve_task(request);
+    let mut unauthorized_client = unauthorized_client().await;
+    let response = unauthorized_client.approve_task(request).await;
     assert!(response.is_err());
 
     let request = ApproveTaskRequest::new(task_id);
-    let response = client.approve_task(request);
+    let response = client.approve_task(request).await;
     assert!(response.is_ok());
 }
 
-#[test_case]
-fn test_invoke_task() {
-    let mut client = authorized_client();
+#[async_test_case]
+async fn test_invoke_task() {
+    let mut client = authorized_client().await;
     let function_id =
         ExternalID::try_from("function-00000000-0000-0000-0000-000000000002").unwrap();
     let external_outfile_url =
@@ -318,45 +367,49 @@
         .function_arguments(hashmap!("arg1" => "arg1_value"))
         .executor(Executor::MesaPy)
         .outputs_ownership(hashmap!("output" => vec!["frontend_user"]));
-    let response = client.create_task(request).unwrap();
-    let task_id = response.task_id;
+    let response = client.create_task(request).await.unwrap().into_inner();
+    let task_id: ExternalID = response.task_id.try_into().unwrap();
 
     let request = RegisterOutputFileRequest::new(external_outfile_url, external_outfile_crypto);
-    let response = client.register_output_file(request).unwrap();
-    let output_id = response.data_id;
-
+    let response = client
+        .register_output_file(request)
+        .await
+        .unwrap()
+        .into_inner();
+    let output_id: ExternalID = response.data_id.try_into().unwrap();
     let request =
         AssignDataRequest::new(task_id.clone(), hashmap!(), hashmap!("output" => output_id));
-    client.assign_data(request).unwrap();
+    client.assign_data(request).await.unwrap();
 
     let request = ApproveTaskRequest::new(task_id.clone());
-    client.approve_task(request).unwrap();
+    client.approve_task(request).await.unwrap();
 
     let request = InvokeTaskRequest::new(task_id.clone());
-    let response = unauthorized_client().invoke_task(request);
+    let mut unauthorized_client = unauthorized_client().await;
+    let response = unauthorized_client.invoke_task(request).await;
     assert!(response.is_err());
 
     let request = InvokeTaskRequest::new(task_id.clone());
-    let response = client.invoke_task(request);
+    let response = client.invoke_task(request).await;
     assert!(response.is_ok());
 
     let request = GetTaskRequest::new(task_id);
-    let response = client.get_task(request).unwrap();
-    assert_eq!(response.status, TaskStatus::Staged);
+    let response = client.get_task(request).await.unwrap().into_inner();
+    assert_eq!(response.status, i32_from_task_status(TaskStatus::Staged));
 
-    let mut scheduler_client = get_scheduler_client();
-    let executor_id = Uuid::new_v4();
+    let mut scheduler_client = get_scheduler_client().await;
+    let executor_id = Uuid::new_v4().to_string();
 
     std::thread::sleep(std::time::Duration::from_secs(2));
 
     let pull_task_request = PullTaskRequest { executor_id };
-    let response = scheduler_client.pull_task(pull_task_request);
+    let response = scheduler_client.pull_task(pull_task_request).await;
     assert!(response.is_ok());
 }
 
-#[test_case]
-fn test_cancel_task() {
-    let mut client = authorized_client();
+#[async_test_case]
+async fn test_cancel_task() {
+    let mut client = authorized_client().await;
     let function_id =
         ExternalID::try_from("function-00000000-0000-0000-0000-000000000002").unwrap();
     let external_outfile_url =
@@ -368,45 +421,52 @@
         .function_arguments(hashmap!("arg1" => "arg1_value"))
         .executor(Executor::MesaPy)
         .outputs_ownership(hashmap!("output" => vec!["frontend_user"]));
-    let response = client.create_task(request).unwrap();
-    let task_id = response.task_id;
+    let response = client.create_task(request).await.unwrap().into_inner();
+    let task_id: ExternalID = response.task_id.try_into().unwrap();
 
     let request = RegisterOutputFileRequest::new(external_outfile_url, external_outfile_crypto);
-    let response = client.register_output_file(request).unwrap();
-    let output_id = response.data_id;
+    let response = client
+        .register_output_file(request)
+        .await
+        .unwrap()
+        .into_inner();
+    let output_id: ExternalID = response.data_id.try_into().unwrap();
 
     let request =
         AssignDataRequest::new(task_id.clone(), hashmap!(), hashmap!("output" => output_id));
-    client.assign_data(request).unwrap();
+    client.assign_data(request).await.unwrap();
 
     let request = ApproveTaskRequest::new(task_id.clone());
-    client.approve_task(request).unwrap();
+    client.approve_task(request).await.unwrap();
 
     let request = InvokeTaskRequest::new(task_id.clone());
-    let response = client.invoke_task(request);
+    let response = client.invoke_task(request).await;
     assert!(response.is_ok());
 
-    let mut scheduler_client = get_scheduler_client();
+    let mut scheduler_client = get_scheduler_client().await;
 
     std::thread::sleep(std::time::Duration::from_secs(5));
 
     let executor_id = Uuid::new_v4();
-    let request = HeartbeatRequest {
-        executor_id,
-        status: ExecutorStatus::Idle,
-    };
+    let request = HeartbeatRequest::new(executor_id, ExecutorStatus::Idle);
 
-    let response = scheduler_client.heartbeat(request).unwrap();
-    assert!(response.command == ExecutorCommand::NewTask);
+    let response = scheduler_client
+        .heartbeat(request)
+        .await
+        .unwrap()
+        .into_inner();
+    assert!(response.command == ExecutorCommand::NewTask as i32);
 
     let request = CancelTaskRequest::new(task_id.clone());
-    let response = client.cancel_task(request);
+    let response = client.cancel_task(request).await;
     assert!(response.is_ok());
 
     std::thread::sleep(std::time::Duration::from_secs(3));
 
-    let pull_task_request = PullTaskRequest { executor_id };
-    let response = scheduler_client.pull_task(pull_task_request);
+    let pull_task_request = PullTaskRequest {
+        executor_id: executor_id.to_string(),
+    };
+    let response = scheduler_client.pull_task(pull_task_request).await;
     log::debug!("response: {:?}", response);
 
     assert!(response.is_err());
@@ -414,14 +474,13 @@
     std::thread::sleep(std::time::Duration::from_secs(3));
 
     let request = GetTaskRequest::new(task_id);
-    let response = client.get_task(request).unwrap();
-
-    assert_eq!(response.status, TaskStatus::Canceled);
+    let response = client.get_task(request).await.unwrap().into_inner();
+    assert_eq!(response.status, i32_from_task_status(TaskStatus::Canceled));
 }
 
-#[test_case]
-fn test_fail_task() {
-    let mut client = authorized_client();
+#[async_test_case]
+async fn test_fail_task() {
+    let mut client = authorized_client().await;
     let function_id =
         ExternalID::try_from("function-00000000-0000-0000-0000-000000000002").unwrap();
     let external_outfile_url =
@@ -433,52 +492,61 @@
         .function_arguments(hashmap!("arg1" => "arg1_value"))
         .executor(Executor::MesaPy)
         .outputs_ownership(hashmap!("output" => vec!["frontend_user"]));
-    let response = client.create_task(request).unwrap();
-    let task_id = response.task_id;
+    let response = client.create_task(request).await.unwrap().into_inner();
+    let task_id: ExternalID = response.task_id.try_into().unwrap();
 
     let request = RegisterOutputFileRequest::new(external_outfile_url, external_outfile_crypto);
-    let response = client.register_output_file(request).unwrap();
-    let output_id = response.data_id;
+    let response = client
+        .register_output_file(request)
+        .await
+        .unwrap()
+        .into_inner();
+    let output_id: ExternalID = response.data_id.try_into().unwrap();
 
     let request =
         AssignDataRequest::new(task_id.clone(), hashmap!(), hashmap!("output" => output_id));
-    client.assign_data(request).unwrap();
+    client.assign_data(request).await.unwrap();
 
     let request = ApproveTaskRequest::new(task_id.clone());
-    client.approve_task(request).unwrap();
+    client.approve_task(request).await.unwrap();
 
     let request = InvokeTaskRequest::new(task_id.clone());
-    let response = client.invoke_task(request);
+    let response = client.invoke_task(request).await;
     assert!(response.is_ok());
 
-    let mut scheduler_client = get_scheduler_client();
+    let mut scheduler_client = get_scheduler_client().await;
 
     std::thread::sleep(std::time::Duration::from_secs(5));
 
     let executor_id = Uuid::new_v4();
-    let request = HeartbeatRequest {
-        executor_id,
-        status: ExecutorStatus::Idle,
-    };
-    let response = scheduler_client.heartbeat(request).unwrap();
-    assert!(response.command == ExecutorCommand::NewTask);
+    let request = HeartbeatRequest::new(executor_id, ExecutorStatus::Idle);
 
-    let pull_task_request = PullTaskRequest { executor_id };
-    let response = scheduler_client.pull_task(pull_task_request).unwrap();
+    let response = scheduler_client
+        .heartbeat(request)
+        .await
+        .unwrap()
+        .into_inner();
+    assert!(response.command == ExecutorCommand::NewTask as i32);
+
+    let pull_task_request = PullTaskRequest {
+        executor_id: executor_id.to_string(),
+    };
+    let response = scheduler_client.pull_task(pull_task_request).await.unwrap();
     log::debug!("response: {:?}", response);
 
-    let request = HeartbeatRequest {
-        executor_id,
-        status: ExecutorStatus::Executing,
-    };
-    let response = scheduler_client.heartbeat(request).unwrap();
+    let request = HeartbeatRequest::new(executor_id, ExecutorStatus::Executing);
+    let response = scheduler_client
+        .heartbeat(request)
+        .await
+        .unwrap()
+        .into_inner();
     log::debug!("response: {:?}", response);
-    assert!(response.command == ExecutorCommand::NoAction);
+    assert!(response.command == ExecutorCommand::NoAction as i32);
 
     std::thread::sleep(std::time::Duration::from_secs(33));
 
     let request = GetTaskRequest::new(task_id);
-    let response = client.get_task(request).unwrap();
+    let response = client.get_task(request).await.unwrap().into_inner();
 
-    assert_eq!(response.status, TaskStatus::Failed);
+    assert_eq!(response.status, i32_from_task_status(TaskStatus::Failed));
 }
diff --git a/tests/functional/enclave/src/lib.rs b/tests/functional/enclave/src/lib.rs
index c909f49..818f02a 100644
--- a/tests/functional/enclave/src/lib.rs
+++ b/tests/functional/enclave/src/lib.rs
@@ -41,13 +41,16 @@
 
 #[handle_ecall]
 fn handle_run_test(input: &RunTestInput) -> TeeServiceResult<RunTestOutput> {
-    utils::setup();
+    let rt = tokio::runtime::Builder::new_current_thread()
+        .enable_all()
+        .build()
+        .unwrap();
+    rt.block_on(utils::setup());
     let ret = if input.test_names.is_empty() {
         run_inventory_tests!()
     } else {
         run_inventory_tests!(|s: &str| input.test_names.iter().any(|t| s.contains(t)))
     };
-
     assert!(ret);
     Ok(RunTestOutput)
 }
diff --git a/tests/functional/enclave/src/management_service.rs b/tests/functional/enclave/src/management_service.rs
index 29b164c..7b73f94 100644
--- a/tests/functional/enclave/src/management_service.rs
+++ b/tests/functional/enclave/src/management_service.rs
@@ -16,115 +16,123 @@
 // under the License.
 
 use crate::utils::*;
+use futures::FutureExt;
 use std::convert::TryFrom;
+use teaclave_proto::teaclave_common::i32_from_task_status;
 use teaclave_proto::teaclave_management_service::*;
 use teaclave_proto::teaclave_scheduler_service::*;
-use teaclave_test_utils::test_case;
+use teaclave_rpc::CredentialService;
+use teaclave_test_utils::async_test_case;
 use teaclave_types::*;
 use url::Url;
 use uuid::Uuid;
 
-fn authorized_client(user_id: &str) -> TeaclaveManagementClient {
-    get_management_client(user_id)
+async fn authorized_client(user_id: &str) -> TeaclaveManagementClient<CredentialService> {
+    get_management_client(user_id).await
 }
 
-#[test_case]
-fn test_register_input_file() {
+#[async_test_case]
+async fn test_register_input_file() {
     let url = Url::parse("https://external-storage.com/filepath?presigned_token").unwrap();
     let cmac = FileAuthTag::mock();
 
     let request = RegisterInputFileRequest::new(url, cmac, FileCrypto::default());
-    let response = authorized_client("mock_user").register_input_file(request);
+    let mut client = authorized_client("mock_user").await;
+    let response = client.register_input_file(request).await;
     assert!(response.is_ok());
 }
 
-#[test_case]
-fn test_register_output_file() {
+#[async_test_case]
+async fn test_register_output_file() {
     let url = Url::parse("https://external-storage.com/filepath?presigned_token").unwrap();
     let crypto_info = FileCrypto::new("aes-gcm-128", &[0x90u8; 16], &[0x89u8; 12]).unwrap();
 
     let request = RegisterOutputFileRequest::new(url, crypto_info);
-    let response = authorized_client("mock_user").register_output_file(request);
-
+    let mut client = authorized_client("mock_user").await;
+    let response = client.register_output_file(request).await;
     assert!(response.is_ok());
 }
 
-#[test_case]
-fn test_register_fusion_output() {
+#[async_test_case]
+async fn test_register_fusion_output() {
     let request = RegisterFusionOutputRequest::new(vec!["mock_user", "mock_user_b"]);
-    let response = authorized_client("mock_user").register_fusion_output(request);
+    let mut client = authorized_client("mock_user").await;
+    let response = client.register_fusion_output(request).await;
     assert!(response.is_ok());
 
     let request = RegisterFusionOutputRequest::new(vec!["mock_user_c", "mock_user_b"]);
-    let response = authorized_client("mock_user").register_fusion_output(request);
+    let response = client.register_fusion_output(request).await;
     assert!(response.is_err());
 }
 
-#[test_case]
-fn test_register_input_from_output() {
+#[async_test_case]
+async fn test_register_input_from_output() {
     let user1_output_id =
         ExternalID::try_from("output-00000000-0000-0000-0000-000000000001").unwrap();
 
     // not a owner
     let request = RegisterInputFromOutputRequest::new(user1_output_id.clone());
-    let response = authorized_client("mock_user_c").register_input_from_output(request);
+    let mut client = authorized_client("mock_user_c").await;
+    let response = client.register_input_from_output(request).await;
     assert!(response.is_err());
 
     // output not ready
     let url = Url::parse("https://external-storage.com/filepath?presigned_token").unwrap();
     let crypto_info = FileCrypto::default();
-    let mut client = authorized_client("mock_user1");
+    let mut client = authorized_client("mock_user1").await;
     let request = RegisterOutputFileRequest::new(url, crypto_info);
-    let response = client.register_output_file(request).unwrap();
-    let request = RegisterInputFromOutputRequest::new(response.data_id);
-    let response = client.register_input_from_output(request);
+    let response = client.register_output_file(request).await.unwrap();
+    let request =
+        RegisterInputFromOutputRequest::new(response.into_inner().data_id.try_into().unwrap());
+    let response = client.register_input_from_output(request).await;
     assert!(response.is_err());
 
     let request = RegisterInputFromOutputRequest::new(user1_output_id);
-    let response = client.register_input_from_output(request);
+    let response = client.register_input_from_output(request).await;
     assert!(response.is_ok());
 }
 
-#[test_case]
-fn test_get_output_file() {
+#[async_test_case]
+async fn test_get_output_file() {
     let url = Url::parse("https://external-storage.com/filepath?presigned_token").unwrap();
     let crypto_info = FileCrypto::default();
     let request = RegisterOutputFileRequest::new(url, crypto_info);
 
-    let mut client = authorized_client("mock_user");
-    let response = client.register_output_file(request).unwrap();
-    let data_id = response.data_id;
+    let mut client = authorized_client("mock_user").await;
+    let response = client.register_output_file(request).await.unwrap();
+    let data_id = ExternalID::try_from(response.into_inner().data_id).unwrap();
     let request = GetOutputFileRequest::new(data_id.clone());
-    let response = client.get_output_file(request);
+    let response = client.get_output_file(request).await;
     assert!(response.is_ok());
 
     let request = GetOutputFileRequest::new(data_id);
-    let response = authorized_client("mock_another_user").get_output_file(request);
+    let mut client = authorized_client("mock_another_user").await;
+    let response = client.get_output_file(request).await;
     assert!(response.is_err());
 }
 
-#[test_case]
-fn test_get_input_file() {
+#[async_test_case]
+async fn test_get_input_file() {
     let url = Url::parse("https://external-storage.com/filepath?presigned_token").unwrap();
     let cmac = FileAuthTag::mock();
     let crypto_info = FileCrypto::default();
 
-    let mut client = authorized_client("mock_user");
+    let mut client = authorized_client("mock_user").await;
     let request = RegisterInputFileRequest::new(url, cmac, crypto_info);
-    let response = client.register_input_file(request).unwrap();
-    let data_id = response.data_id;
+    let response = client.register_input_file(request).await;
+    let data_id = ExternalID::try_from(response.unwrap().into_inner().data_id).unwrap();
     let request = GetInputFileRequest::new(data_id.clone());
-    let response = client.get_input_file(request);
+    let response = client.get_input_file(request).await;
     assert!(response.is_ok());
 
-    let mut client = authorized_client("mock_another_user");
+    let mut client = authorized_client("mock_another_user").await;
     let request = GetInputFileRequest::new(data_id);
-    let response = client.get_input_file(request);
+    let response = client.get_input_file(request).await;
     assert!(response.is_err());
 }
 
-#[test_case]
-fn test_register_function() {
+#[async_test_case]
+async fn test_register_function() {
     let function_input = FunctionInput::new("input", "input_desc", false);
     let function_output = FunctionOutput::new("output", "output_desc", false);
     let request = RegisterFunctionRequestBuilder::new()
@@ -138,14 +146,13 @@
         .usage_quota(Some(0))
         .build();
 
-    let mut client = authorized_client("mock_user");
-    let response = client.register_function(request);
-
+    let mut client = authorized_client("mock_user").await;
+    let response = client.register_function(request).await;
     assert!(response.is_ok());
 }
 
-#[test_case]
-fn test_register_private_function() {
+#[async_test_case]
+async fn test_register_private_function() {
     let function_input = FunctionInput::new("input", "input_desc", false);
     let function_output = FunctionOutput::new("output", "output_desc", false);
     let request = RegisterFunctionRequestBuilder::new()
@@ -159,14 +166,14 @@
         .user_allowlist(vec!["mock_user".to_string()])
         .build();
 
-    let mut client = authorized_client("mock_user");
-    let response = client.register_function(request);
+    let mut client = authorized_client("mock_user").await;
+    let response = client.register_function(request).await;
 
     assert!(response.is_ok());
 }
 
-#[test_case]
-fn test_delete_function() {
+#[async_test_case]
+async fn test_delete_function() {
     let function_input = FunctionInput::new("input", "input_desc", false);
     let function_output = FunctionOutput::new("output", "output_desc", false);
     let request = RegisterFunctionRequestBuilder::new()
@@ -179,17 +186,17 @@
         .outputs(vec![function_output])
         .build();
 
-    let mut client = authorized_client("mock_user");
-    let response = client.register_function(request);
-    let function_id = response.unwrap().function_id;
+    let mut client = authorized_client("mock_user").await;
+    let response = client.register_function(request).await.unwrap();
+    let function_id = ExternalID::try_from(response.into_inner().function_id).unwrap();
 
     let request = DeleteFunctionRequest::new(function_id);
-    let response = client.delete_function(request);
+    let response = client.delete_function(request).await;
     assert!(response.is_ok());
 }
 
-#[test_case]
-fn test_disable_function() {
+#[async_test_case]
+async fn test_disable_function() {
     let function_input = FunctionInput::new("input", "input_desc", false);
     let function_output = FunctionOutput::new("output", "output_desc", false);
     let request = RegisterFunctionRequestBuilder::new()
@@ -202,17 +209,21 @@
         .outputs(vec![function_output])
         .build();
 
-    let mut client = authorized_client("mock_user");
-    let response = client.register_function(request);
-    let function_id = response.unwrap().function_id;
+    let mut client = authorized_client("mock_user").await;
+    let response = client
+        .register_function(request)
+        .await
+        .unwrap()
+        .into_inner();
+    let function_id = ExternalID::try_from(response.function_id).unwrap();
 
     let request = DisableFunctionRequest::new(function_id);
-    let response = client.disable_function(request);
+    let response = client.disable_function(request).await;
     assert!(response.is_ok());
 }
 
-#[test_case]
-fn test_update_function() {
+#[async_test_case]
+async fn test_update_function() {
     let function_input = FunctionInput::new("input", "input_desc", false);
     let function_output = FunctionOutput::new("output", "output_desc", false);
     let request = RegisterFunctionRequestBuilder::new()
@@ -225,9 +236,9 @@
         .outputs(vec![function_output])
         .build();
 
-    let mut client = authorized_client("mock_user");
-    let response = client.register_function(request);
-    let original_id = response.unwrap().function_id;
+    let mut client = authorized_client("mock_user").await;
+    let response = client.register_function(request).await;
+    let original_id = ExternalID::try_from(response.unwrap().into_inner().function_id).unwrap();
 
     let function_input = FunctionInput::new("input", "input_desc", false);
     let function_output = FunctionOutput::new("output", "output_desc", false);
@@ -243,27 +254,25 @@
         .user_allowlist(vec!["mock_user".to_string()])
         .build();
 
-    let mut client = authorized_client("mock_user");
-    let response = client.update_function(request);
-
+    let mut client = authorized_client("mock_user").await;
+    let response = client.update_function(request).await;
     assert!(response.is_ok());
-    assert!(original_id == response.unwrap().function_id);
+    assert!(original_id.to_string() == response.unwrap().into_inner().function_id);
 }
 
-#[test_case]
-fn test_list_functions() {
+#[async_test_case]
+async fn test_list_functions() {
     let request = ListFunctionsRequest {
         user_id: "mock_user".into(),
     };
 
-    let mut client = authorized_client("mock_user");
-    let response = client.list_functions(request);
-
+    let mut client = authorized_client("mock_user").await;
+    let response = client.list_functions(request).await;
     assert!(response.is_ok());
 }
 
-#[test_case]
-fn test_get_function() {
+#[async_test_case]
+async fn test_get_function() {
     let function_input = FunctionInput::new("input", "input_desc", false);
     let function_output = FunctionOutput::new("output", "output_desc", false);
     let request = RegisterFunctionRequestBuilder::new()
@@ -276,43 +285,47 @@
         .outputs(vec![function_output])
         .build();
 
-    let mut client = authorized_client("mock_user");
-    let response = client.register_function(request).unwrap();
-    let function_id = response.function_id;
+    let mut client = authorized_client("mock_user").await;
+    let response = client
+        .register_function(request)
+        .await
+        .unwrap()
+        .into_inner();
+    let function_id = ExternalID::try_from(response.function_id).unwrap();
 
     let request = GetFunctionRequest::new(function_id.clone());
-    let response = client.get_function(request);
+    let response = client.get_function(request).await;
     assert!(response.is_ok());
 
-    let mut client = authorized_client("mock_unauthorized_user");
+    let mut client = authorized_client("mock_unauthorized_user").await;
     let request = GetFunctionRequest::new(function_id);
-    let response = client.get_function(request);
+    let response = client.get_function(request).await;
     // mock_unauthorized_user is PlatformAdmin
     assert!(response.is_ok());
 
     let function_id =
         ExternalID::try_from("function-00000000-0000-0000-0000-000000000001").unwrap();
     let request = GetFunctionRequest::new(function_id);
-    let response = client.get_function(request);
+    let response = client.get_function(request).await;
     assert!(response.is_ok());
 
     // private functions
     let function_id =
         ExternalID::try_from("function-00000000-0000-0000-0000-000000000003").unwrap();
 
-    let mut client = authorized_client("mock_user");
+    let mut client = authorized_client("mock_user").await;
     let request = GetFunctionRequest::new(function_id.clone());
-    let response = client.get_function(request);
+    let response = client.get_function(request).await;
     assert!(response.is_ok());
 
-    let mut client = authorized_client("mock_user1");
+    let mut client = authorized_client("mock_user1").await;
     let request = GetFunctionRequest::new(function_id.clone());
-    let response = client.get_function(request);
+    let response = client.get_function(request).await;
     assert!(response.is_ok());
 
-    let mut client = authorized_client("mock_unauthorized_user");
+    let mut client = authorized_client("mock_unauthorized_user").await;
     let request = GetFunctionRequest::new(function_id);
-    let response = client.get_function(request);
+    let response = client.get_function(request).await;
     // mock_unauthorized_user is PlatformAdmin
     assert!(response.is_ok());
 }
@@ -347,110 +360,120 @@
         .executor(Executor::MesaPy)
 }
 
-#[test_case]
-fn test_create_task() {
-    let mut client = authorized_client("mock_user");
+#[async_test_case]
+async fn test_create_task() {
+    let mut client = authorized_client("mock_user").await;
 
     let request = CreateTaskRequest::new().executor(Executor::MesaPy);
-    let response = client.create_task(request);
+    let response = client.create_task(request).await;
     assert!(response.is_err());
 
     let request = create_valid_task_request();
-    let response = client.create_task(request);
+    let response = client.create_task(request).await;
     assert!(response.is_ok());
 
     let request = create_valid_task_request_private_function();
-    let response = client.create_task(request);
+    let response = client.create_task(request).await;
     assert!(response.is_ok());
 
     let mut request = create_valid_task_request();
-    request.function_arguments.inner_mut().remove("arg1");
-    let response = client.create_task(request);
+    let mut function_arguments: FunctionArguments = request.function_arguments.try_into().unwrap();
+    function_arguments.inner_mut().remove("arg1");
+    request.function_arguments = function_arguments.into_string();
+    let response = client.create_task(request).await;
     assert!(response.is_err());
 
     let mut request = create_valid_task_request();
     request = request.inputs_ownership(hashmap!(
         "input2" => vec!["mock_user2", "mock_user3"]
     ));
-    let response = client.create_task(request);
+    let response = client.create_task(request).await;
     assert!(response.is_err());
 
     let mut request = create_valid_task_request();
     request = request.outputs_ownership(hashmap!(
             "output2" => vec!["mock_user2", "mock_user3"]
     ));
-    let response = client.create_task(request);
+    let response = client.create_task(request).await;
     assert!(response.is_err());
 
-    let mut client = authorized_client("mock_user2");
+    let mut client = authorized_client("mock_user2").await;
     let request = create_valid_task_request_private_function();
-    let response = client.create_task(request);
+    let response = client.create_task(request).await;
     // PlatformAdmin can access private function
     assert!(response.is_ok());
 }
 
-#[test_case]
-fn test_get_task() {
-    let mut client = authorized_client("mock_user");
+#[async_test_case]
+async fn test_get_task() {
+    let mut client = authorized_client("mock_user").await;
 
     let request = create_valid_task_request();
-    let response = client.create_task(request).unwrap();
-    let task_id = response.task_id;
+    let response = client.create_task(request).await.unwrap();
+    let task_id = ExternalID::try_from(response.into_inner().task_id).unwrap();
 
     let request = GetTaskRequest::new(task_id);
-    let response = client.get_task(request).unwrap();
+    let response = client.get_task(request).await.unwrap().into_inner();
     assert!(response.participants.len() == 4);
 
     let participants = vec!["mock_user1", "mock_user3", "mock_user2", "mock_user"];
     for name in participants {
-        assert!(response.participants.contains(&UserID::from(name)));
+        assert!(response.participants.contains(&name.to_string()));
     }
 }
 
-#[test_case]
-fn test_assign_data() {
-    let mut client = authorized_client("mock_user");
-    let mut client1 = authorized_client("mock_user1");
-    let mut client2 = authorized_client("mock_user2");
-    let mut client3 = authorized_client("mock_user3");
+#[async_test_case]
+async fn test_assign_data() {
+    let mut client = authorized_client("mock_user").await;
+    let mut client1 = authorized_client("mock_user1").await;
+    let mut client2 = authorized_client("mock_user2").await;
+    let mut client3 = authorized_client("mock_user3").await;
     let request = create_valid_task_request();
-    let response = client.create_task(request).unwrap();
-    let task_id = response.task_id;
+    let response = client.create_task(request).await.unwrap().into_inner();
+    let task_id = ExternalID::try_from(response.task_id).unwrap();
 
     // not a participant
     let request = AssignDataRequest::new(task_id.clone(), hashmap!(), hashmap!());
 
-    let mut unknown_client = authorized_client("non-participant");
-    let response = unknown_client.assign_data(request);
+    let mut unknown_client = authorized_client("non-participant").await;
+    let response = unknown_client.assign_data(request).await;
     assert!(response.is_err());
 
     // !input_file.owner.contains(user_id)
     let url = Url::parse("https://path").unwrap();
     let cmac = FileAuthTag::mock();
     let request = RegisterInputFileRequest::new(url, cmac, FileCrypto::default());
-    let response = client2.register_input_file(request).unwrap();
-    let input_file_id_user2 = response.data_id;
+    let response = client2
+        .register_input_file(request)
+        .await
+        .unwrap()
+        .into_inner();
+    let input_file_id_user2 = ExternalID::try_from(response.data_id).unwrap();
 
     let request = AssignDataRequest::new(
         task_id.clone(),
         hashmap!("input" => input_file_id_user2.clone()),
         hashmap!(),
     );
-    let response = client1.assign_data(request);
+    let response = client1.assign_data(request).await;
     assert!(response.is_err());
 
     // !output_file.owner.contains(user_id)
     let url = Url::parse("https://output_file_path").unwrap();
     let request = RegisterOutputFileRequest::new(url, FileCrypto::default());
-    let response = client2.register_output_file(request).unwrap();
-    let output_file_id_user2 = response.data_id;
+    let response = client2
+        .register_output_file(request)
+        .await
+        .unwrap()
+        .into_inner();
+    let output_file_id_user2 = ExternalID::try_from(response.data_id).unwrap();
 
     let request = AssignDataRequest::new(
         task_id.clone(),
         hashmap!(),
         hashmap!("output" => output_file_id_user2.clone()),
     );
-    let response = client1.assign_data(request);
+    let response = client1.assign_data(request).await;
     assert!(response.is_err());
 
     let existing_outfile_id_user1 =
@@ -458,14 +481,14 @@
 
     // output_file.cmac.is_some()
     let request = GetOutputFileRequest::new(existing_outfile_id_user1.clone());
-    client1.get_output_file(request).unwrap();
+    client1.get_output_file(request).await.unwrap();
 
     let request = AssignDataRequest::new(
         task_id.clone(),
         hashmap!(),
         hashmap!("output" => existing_outfile_id_user1),
     );
-    let response = client1.assign_data(request);
+    let response = client1.assign_data(request).await;
     assert!(response.is_err());
 
     // !fusion_data.owner_id_list.contains(user_id)
@@ -475,7 +498,7 @@
         hashmap!("input" => file_id2.clone()),
         hashmap!(),
     );
-    let response = client1.assign_data(request);
+    let response = client1.assign_data(request).await;
     assert!(response.is_err());
 
     // inputs_ownership doesn't contain the name
@@ -484,7 +507,7 @@
         hashmap!("none" => input_file_id_user2.clone()),
         hashmap!(),
     );
-    let response = client2.assign_data(request);
+    let response = client2.assign_data(request).await;
     assert!(response.is_err());
 
     // outputs_ownership doesn't contain the name
@@ -493,7 +516,7 @@
         hashmap!(),
         hashmap!("none" => output_file_id_user2.clone()),
     );
-    let response = client2.assign_data(request);
+    let response = client2.assign_data(request).await;
     assert!(response.is_err());
 
     //input file: OwnerList != user_id
@@ -502,7 +525,7 @@
         hashmap!("input2" => input_file_id_user2.clone()),
         hashmap!(),
     );
-    let response = client2.assign_data(request);
+    let response = client2.assign_data(request).await;
     assert!(response.is_err());
 
     // input file: OwnerList != user_id
@@ -511,7 +534,7 @@
         hashmap!("input" => input_file_id_user2),
         hashmap!(),
     );
-    let response = client2.assign_data(request);
+    let response = client2.assign_data(request).await;
     assert!(response.is_err());
 
     // output file OwnerList != uids
@@ -520,7 +543,7 @@
         hashmap!(),
         hashmap!("output2" => output_file_id_user2.clone()),
     );
-    let response = client2.assign_data(request);
+    let response = client2.assign_data(request).await;
     assert!(response.is_err());
 
     // output file: OwnerList != uids
@@ -529,48 +552,63 @@
         hashmap!(),
         hashmap!("output1" => output_file_id_user2),
     );
-    let response = client2.assign_data(request);
+    let response = client2.assign_data(request).await;
     assert!(response.is_err());
 
     // assign all the data
     let url = Url::parse("input://path").unwrap();
     let cmac = FileAuthTag::mock();
     let request = RegisterInputFileRequest::new(url, cmac, FileCrypto::default());
-    let response = client1.register_input_file(request);
-    let input_file_id_user1 = response.unwrap().data_id;
+    let response = client1
+        .register_input_file(request)
+        .await
+        .unwrap()
+        .into_inner();
+    let input_file_id_user1 = ExternalID::try_from(response.data_id).unwrap();
 
     let url = Url::parse("https://output_file_path").unwrap();
     let request = RegisterOutputFileRequest::new(url, FileCrypto::default());
-    let response = client1.register_output_file(request);
-    let output_file_id_user1 = response.unwrap().data_id;
+    let response = client1
+        .register_output_file(request)
+        .await
+        .unwrap()
+        .into_inner();
+    let output_file_id_user1 = ExternalID::try_from(response.data_id).unwrap();
 
     let request = AssignDataRequest::new(
         task_id.clone(),
         hashmap!("input" => input_file_id_user1.clone()),
         hashmap!("output" => output_file_id_user1),
     );
-    let response = client1.assign_data(request);
+    let response = client1.assign_data(request).await;
     assert!(response.is_ok());
 
     let request =
         AssignDataRequest::new(task_id.clone(), hashmap!("input2" => file_id2), hashmap!());
-    let response = client3.assign_data(request);
+    let response = client3.assign_data(request).await;
     assert!(response.is_ok());
 
     let request = RegisterFusionOutputRequest::new(vec!["mock_user2", "mock_user3"]);
-    let response = client3.register_fusion_output(request).unwrap();
-    let fusion_output = response.data_id;
+    let response = client3
+        .register_fusion_output(request)
+        .await
+        .unwrap()
+        .into_inner();
+    let fusion_output = ExternalID::try_from(response.data_id).unwrap();
     let request = AssignDataRequest::new(
         task_id.clone(),
         hashmap!(),
         hashmap!("output2" => fusion_output),
     );
-    let response = client3.assign_data(request);
+    let response = client3.assign_data(request).await;
     assert!(response.is_ok());
 
     let request = GetTaskRequest::new(task_id.clone());
-    let response = client3.get_task(request).unwrap();
-    assert_eq!(response.status, TaskStatus::DataAssigned);
+    let response = client3.get_task(request).await.unwrap().into_inner();
+    assert_eq!(
+        response.status,
+        i32_from_task_status(TaskStatus::DataAssigned)
+    );
 
     // task.status != Created
     let request = AssignDataRequest::new(
@@ -578,43 +616,49 @@
         hashmap!("input" => input_file_id_user1),
         hashmap!(),
     );
-    let response = client1.assign_data(request);
+    let response = client1.assign_data(request).await;
     assert!(response.is_err());
 }
 
-#[test_case]
-fn test_approve_task() {
-    let mut client = authorized_client("mock_user");
-    let mut client1 = authorized_client("mock_user1");
-    let mut client2 = authorized_client("mock_user2");
-    let mut client3 = authorized_client("mock_user3");
+#[async_test_case]
+async fn test_approve_task() {
+    let mut client = authorized_client("mock_user").await;
+    let mut client1 = authorized_client("mock_user1").await;
+    let mut client2 = authorized_client("mock_user2").await;
+    let mut client3 = authorized_client("mock_user3").await;
     let request = create_valid_task_request();
-    let response = client.create_task(request).unwrap();
-    let task_id = response.task_id;
+    let response = client.create_task(request).await.unwrap().into_inner();
+    let task_id = ExternalID::try_from(response.task_id).unwrap();
 
     // task_status != ready
     let request = ApproveTaskRequest::new(task_id.clone());
-    let response = client1.approve_task(request);
+    let response = client1.approve_task(request).await;
     assert!(response.is_err());
 
     // assign all the data
     let url = Url::parse("input://path").unwrap();
     let cmac = FileAuthTag::mock();
     let request = RegisterInputFileRequest::new(url, cmac, FileCrypto::default());
-    let response = client1.register_input_file(request).unwrap();
-
-    let input_file_id_user1 = response.data_id;
+    let response = client1
+        .register_input_file(request)
+        .await
+        .unwrap()
+        .into_inner();
+    let input_file_id_user1 = ExternalID::try_from(response.data_id).unwrap();
     let url = Url::parse("https://output_file_path").unwrap();
     let request = RegisterOutputFileRequest::new(url, FileCrypto::default());
-    let response = client1.register_output_file(request).unwrap();
-
-    let output_file_id_user1 = response.data_id;
+    let response = client1
+        .register_output_file(request)
+        .await
+        .unwrap()
+        .into_inner();
+    let output_file_id_user1 = ExternalID::try_from(response.data_id).unwrap();
     let request = AssignDataRequest::new(
         task_id.clone(),
         hashmap!("input" => input_file_id_user1),
         hashmap!("output" => output_file_id_user1),
     );
-    let response = client1.assign_data(request);
+    let response = client1.assign_data(request).await;
     assert!(response.is_ok());
 
     let input_file_id_user2 =
@@ -624,78 +668,89 @@
         hashmap!("input2" => input_file_id_user2),
         hashmap!(),
     );
-    let response = client2.assign_data(request);
+    let response = client2.assign_data(request).await;
     assert!(response.is_ok());
 
     let request = RegisterFusionOutputRequest::new(vec!["mock_user2", "mock_user3"]);
-    let response = client3.register_fusion_output(request);
-    let fusion_output = response.unwrap().data_id;
+    let response = client3.register_fusion_output(request).await;
+    let fusion_output = ExternalID::try_from(response.unwrap().into_inner().data_id).unwrap();
     let request = AssignDataRequest::new(
         task_id.clone(),
         hashmap!(),
         hashmap!("output2" => fusion_output),
     );
-    let response = client3.assign_data(request);
+    let response = client3.assign_data(request).await;
     assert!(response.is_ok());
 
     let request = GetTaskRequest::new(task_id.clone());
-    let response = client2.get_task(request).unwrap();
-    assert_eq!(response.status, TaskStatus::DataAssigned);
+    let response = client2.get_task(request).await.unwrap().into_inner();
+    assert_eq!(
+        response.status,
+        i32_from_task_status(TaskStatus::DataAssigned)
+    );
 
     // user_id not in task.participants
-    let mut unknown_client = authorized_client("non-participant");
+    let mut unknown_client = authorized_client("non-participant").await;
     let request = ApproveTaskRequest::new(task_id.clone());
-    let response = unknown_client.approve_task(request);
+    let response = unknown_client.approve_task(request).await;
     assert!(response.is_err());
 
     //all participants approve the task
     let request = ApproveTaskRequest::new(task_id.clone());
-    let response = client.approve_task(request);
+    let response = client.approve_task(request).await;
     assert!(response.is_ok());
     let request = ApproveTaskRequest::new(task_id.clone());
-    let response = client1.approve_task(request);
+    let response = client1.approve_task(request).await;
     assert!(response.is_ok());
     let request = ApproveTaskRequest::new(task_id.clone());
-    let response = client2.approve_task(request);
+    let response = client2.approve_task(request).await;
     assert!(response.is_ok());
     let request = ApproveTaskRequest::new(task_id.clone());
-    let response = client3.approve_task(request);
+    let response = client3.approve_task(request).await;
     assert!(response.is_ok());
     let request = GetTaskRequest::new(task_id);
-    let response = client2.get_task(request).unwrap();
-    assert_eq!(response.status, TaskStatus::Approved);
+    let response = client2.get_task(request).await.unwrap().into_inner();
+    assert_eq!(response.status, i32_from_task_status(TaskStatus::Approved));
 }
 
-#[test_case]
-fn test_invoke_task() {
-    let mut client = authorized_client("mock_user");
-    let mut client1 = authorized_client("mock_user1");
-    let mut client2 = authorized_client("mock_user2");
-    let mut client3 = authorized_client("mock_user3");
+#[async_test_case]
+async fn test_invoke_task() {
+    let mut client = authorized_client("mock_user").await;
+    let mut client1 = authorized_client("mock_user1").await;
+    let mut client2 = authorized_client("mock_user2").await;
+    let mut client3 = authorized_client("mock_user3").await;
     let request = create_valid_task_request();
-    let response = client.create_task(request);
+    let response = client.create_task(request).await;
     assert!(response.is_ok());
-    let task_id = response.unwrap().task_id;
+    let task_id: ExternalID = response.unwrap().into_inner().task_id.try_into().unwrap();
 
     // assign all the data
     let url = Url::parse("input://path").unwrap();
     let cmac = FileAuthTag::mock();
     let request = RegisterInputFileRequest::new(url, cmac, FileCrypto::default());
-    let response = client1.register_input_file(request).unwrap();
+    let response = client1
+        .register_input_file(request)
+        .await
+        .unwrap()
+        .into_inner();
 
-    let input_file_id_user1 = response.data_id;
+    let input_file_id_user1: ExternalID = response.data_id.try_into().unwrap();
 
     let url = Url::parse("https://output_file_path").unwrap();
     let request = RegisterOutputFileRequest::new(url, FileCrypto::default());
-    let response = client1.register_output_file(request).unwrap();
-    let output_file_id_user1 = response.data_id;
+    let response = client1
+        .register_output_file(request)
+        .await
+        .unwrap()
+        .into_inner();
+    let output_file_id_user1: ExternalID = response.data_id.try_into().unwrap();
 
     let request = AssignDataRequest::new(
         task_id.clone(),
         hashmap!("input" => input_file_id_user1),
         hashmap!("output" => output_file_id_user1),
     );
-    client1.assign_data(request).unwrap();
+    client1.assign_data(request).await.unwrap();
 
     let input_file_id_user2 =
         ExternalID::try_from("input-00000000-0000-0000-0000-000000000002").unwrap();
@@ -704,57 +759,57 @@
         hashmap!("input2" => input_file_id_user2),
         hashmap!(),
     );
-    let response = client2.assign_data(request);
+    let response = client2.assign_data(request).await;
     assert!(response.is_ok());
 
     let request = RegisterFusionOutputRequest::new(vec!["mock_user2", "mock_user3"]);
-    let response = client3.register_fusion_output(request);
-    let fusion_output = response.unwrap().data_id;
+    let response = client3.register_fusion_output(request).await;
+    let fusion_output = ExternalID::try_from(response.unwrap().into_inner().data_id).unwrap();
     let request = AssignDataRequest::new(
         task_id.clone(),
         hashmap!(),
         hashmap!("output2" => fusion_output),
     );
-    let response = client3.assign_data(request);
+    let response = client3.assign_data(request).await;
     assert!(response.is_ok());
 
     // task status != Approved
     let request = InvokeTaskRequest::new(task_id.clone());
-    let response = client.invoke_task(request);
+    let response = client.invoke_task(request).await;
     assert!(response.is_err());
 
     //all participants approve the task
     let request = ApproveTaskRequest::new(task_id.clone());
-    client.approve_task(request).unwrap();
+    client.approve_task(request).await.unwrap();
     let request = ApproveTaskRequest::new(task_id.clone());
-    client1.approve_task(request).unwrap();
+    client1.approve_task(request).await.unwrap();
     let request = ApproveTaskRequest::new(task_id.clone());
-    client2.approve_task(request).unwrap();
+    client2.approve_task(request).await.unwrap();
     let request = ApproveTaskRequest::new(task_id.clone());
-    client3.approve_task(request).unwrap();
+    client3.approve_task(request).await.unwrap();
     let request = GetTaskRequest::new(task_id.clone());
-    let response = client2.get_task(request).unwrap();
-    assert_eq!(response.status, TaskStatus::Approved);
+    let response = client2.get_task(request).await.unwrap().into_inner();
+    assert_eq!(response.status, i32_from_task_status(TaskStatus::Approved));
 
     // user_id != task.creator
     let request = InvokeTaskRequest::new(task_id.clone());
-    let response = client2.invoke_task(request);
+    let response = client2.invoke_task(request).await;
     assert!(response.is_err());
 
     // invoke task
     let request = InvokeTaskRequest::new(task_id.clone());
-    client.invoke_task(request).unwrap();
+    client.invoke_task(request).await.unwrap();
 
     let request = GetTaskRequest::new(task_id);
-    let response = client2.get_task(request).unwrap();
-    assert_eq!(response.status, TaskStatus::Staged);
+    let response = client2.get_task(request).await.unwrap().into_inner();
+    assert_eq!(response.status, i32_from_task_status(TaskStatus::Staged));
 
-    let mut scheduler_client = get_scheduler_client();
-    let executor_id = Uuid::new_v4();
+    let mut scheduler_client = get_scheduler_client().await;
+    let executor_id = Uuid::new_v4().to_string();
 
     std::thread::sleep(std::time::Duration::from_secs(2));
 
     let pull_task_request = PullTaskRequest { executor_id };
-    let response = scheduler_client.pull_task(pull_task_request);
+    let response = scheduler_client.pull_task(pull_task_request).await;
     assert!(response.is_ok());
 }
diff --git a/tests/functional/enclave/src/scheduler_service.rs b/tests/functional/enclave/src/scheduler_service.rs
index e660490..65c41f4 100644
--- a/tests/functional/enclave/src/scheduler_service.rs
+++ b/tests/functional/enclave/src/scheduler_service.rs
@@ -16,16 +16,15 @@
 // under the License.
 
 use crate::utils::*;
-
+use futures::FutureExt;
 use teaclave_proto::teaclave_scheduler_service::*;
 use teaclave_proto::teaclave_storage_service::*;
-use teaclave_test_utils::test_case;
+use teaclave_test_utils::async_test_case;
 use teaclave_types::*;
-
 use uuid::Uuid;
 
-#[test_case]
-fn test_pull_task() {
+#[async_test_case]
+async fn test_pull_task() {
     let function_id = Uuid::new_v4();
     let staged_task = StagedTaskBuilder::new()
         .task_id(Uuid::new_v4())
@@ -34,35 +33,34 @@
         .executor(Executor::Builtin)
         .build();
 
-    let mut storage_client = get_storage_client();
+    let mut storage_client = get_storage_client().await;
     let enqueue_request = EnqueueRequest::new(
         StagedTask::get_queue_key().as_bytes(),
         staged_task.to_vec().unwrap(),
     );
-    let _enqueue_response = storage_client.enqueue(enqueue_request).unwrap();
-
-    let mut client = get_scheduler_client();
-    let executor_id = Uuid::new_v4();
+    let _enqueue_response = storage_client.enqueue(enqueue_request).await.unwrap();
+    let mut client = get_scheduler_client().await;
+    let executor_id = Uuid::new_v4().to_string();
 
     std::thread::sleep(std::time::Duration::from_secs(2));
 
     let pull_task_request = PullTaskRequest { executor_id };
-    let response = client.pull_task(pull_task_request);
+    let response = client.pull_task(pull_task_request).await;
     log::debug!("response: {:?}", response);
 
     assert!(response.is_ok());
 
-    let response = response.unwrap();
+    let staged_task = StagedTask::from_slice(&response.unwrap().into_inner().staged_task).unwrap();
     log::info!(
         "pulled staged_task function_id: {:?}",
-        response.staged_task.function_id
+        staged_task.function_id
     );
 
-    assert_eq!(response.staged_task.function_id, function_id);
+    assert_eq!(staged_task.function_id, function_id);
 }
 
-#[test_case]
-fn test_update_task_status_result() {
+#[async_test_case]
+async fn test_update_task_status_result() {
     let task_id = Uuid::new_v4();
     let function_id = Uuid::new_v4();
 
@@ -73,39 +71,42 @@
         .executor(Executor::Builtin)
         .build();
 
-    let mut storage_client = get_storage_client();
+    let mut storage_client = get_storage_client().await;
     let enqueue_request = EnqueueRequest::new(
         StagedTask::get_queue_key().as_bytes(),
         staged_task.to_vec().unwrap(),
     );
-    let _enqueue_response = storage_client.enqueue(enqueue_request).unwrap();
-
+    let _enqueue_response = storage_client.enqueue(enqueue_request).await.unwrap();
     let ts = TaskState {
         task_id,
         status: TaskStatus::Staged,
         ..Default::default()
     };
     let put_request = PutRequest::new(ts.key().as_slice(), ts.to_vec().unwrap().as_slice());
-    let _put_response = storage_client.put(put_request).unwrap();
+    let _put_response = storage_client.put(put_request).await.unwrap();
+    let mut client = get_scheduler_client().await;
 
-    let mut client = get_scheduler_client();
-
-    let executor_id = Uuid::new_v4();
+    let executor_id = Uuid::new_v4().to_string();
 
     std::thread::sleep(std::time::Duration::from_secs(2));
 
     let pull_task_request = PullTaskRequest { executor_id };
-    let response = client.pull_task(pull_task_request).unwrap();
+    let response = client
+        .pull_task(pull_task_request)
+        .await
+        .unwrap()
+        .into_inner();
     log::debug!("response: {:?}", response);
-    let task_id = response.staged_task.task_id;
+    let task_id = StagedTask::from_slice(&response.staged_task)
+        .unwrap()
+        .task_id;
 
     let request = UpdateTaskStatusRequest::new(task_id, TaskStatus::Running);
-    let response = client.update_task_status(request);
+    let response = client.update_task_status(request).await;
     assert!(response.is_ok());
 
     let task_outputs = TaskOutputs::new("return value", hashmap!(), vec![]);
     let request = UpdateTaskResultRequest::new(task_id, Ok(task_outputs));
-    let response = client.update_task_result(request);
-
+    let response = client.update_task_result(request).await;
     assert!(response.is_ok());
 }
diff --git a/tests/functional/enclave/src/storage_service.rs b/tests/functional/enclave/src/storage_service.rs
index 24a3bce..6c815ea 100644
--- a/tests/functional/enclave/src/storage_service.rs
+++ b/tests/functional/enclave/src/storage_service.rs
@@ -15,110 +15,125 @@
 // specific language governing permissions and limitations
 // under the License.
 
+use crate::utils::create_client_config;
+use futures::FutureExt;
 use teaclave_config::RuntimeConfig;
 use teaclave_proto::teaclave_storage_service::*;
-use teaclave_rpc::endpoint::Endpoint;
-use teaclave_test_utils::test_case;
+use teaclave_rpc::{
+    transport::{Channel, Uri},
+    CredentialService,
+};
+use teaclave_test_utils::async_test_case;
 
-fn get_client() -> TeaclaveStorageClient {
+async fn get_client() -> TeaclaveStorageClient<CredentialService> {
     let runtime_config = RuntimeConfig::from_toml("runtime.config.toml").expect("runtime");
-    let channel = Endpoint::new(&runtime_config.internal_endpoints.storage.advertised_address)
+    let enclave_info =
+        teaclave_types::EnclaveInfo::from_bytes(&runtime_config.audit.enclave_info_bytes);
+    let tls_config = create_client_config(&enclave_info, "teaclave_storage_service").unwrap();
+    let service_addr = runtime_config.internal_endpoints.storage.advertised_address;
+    let channel = Channel::builder(service_addr.parse::<Uri>().unwrap())
+        .tls_config(tls_config)
+        .unwrap()
         .connect()
+        .await
         .unwrap();
-    TeaclaveStorageClient::new(channel).unwrap()
+    TeaclaveStorageClient::with_interceptor(channel, teaclave_rpc::UserCredential::default())
 }
 
-#[test_case]
-fn test_get_success() {
-    let mut client = get_client();
+#[async_test_case]
+async fn test_get_success() {
+    let mut client = get_client().await;
     let request = GetRequest::new("test_get_key");
-    let response_result = client.get(request);
-    debug!("{:?}", response_result);
+    let response_result = client.get(request).await;
+    println!("{:?}", response_result);
     assert!(response_result.is_ok());
 }
 
-#[test_case]
-fn test_get_fail() {
-    let mut client = get_client();
+#[async_test_case]
+async fn test_get_fail() {
+    let mut client = get_client().await;
     let request = GetRequest::new("test_key_not_exist");
-    let response_result = client.get(request);
+    let response_result = client.get(request).await;
     assert!(response_result.is_err());
 }
 
-#[test_case]
-fn test_put_success() {
-    let mut client = get_client();
+#[async_test_case]
+async fn test_put_success() {
+    let mut client = get_client().await;
     let request = PutRequest::new("test_put_key", "test_put_value");
-    let response_result = client.put(request);
+    let response_result = client.put(request).await;
     debug!("{:?}", response_result);
     assert!(response_result.is_ok());
 
     let request = GetRequest::new("test_put_key");
-    let response_result = client.get(request);
+    let response_result = client.get(request).await;
     debug!("{:?}", response_result);
     assert!(response_result.is_ok());
-    assert_eq!(response_result.unwrap().value, b"test_put_value");
+    assert_eq!(
+        response_result.unwrap().into_inner().value,
+        b"test_put_value"
+    );
 }
 
-#[test_case]
-fn test_delete_success() {
-    let mut client = get_client();
+#[async_test_case]
+async fn test_delete_success() {
+    let mut client = get_client().await;
     let request = DeleteRequest::new("test_delete_key");
-    let response_result = client.delete(request);
+    let response_result = client.delete(request).await;
     debug!("{:?}", response_result);
     assert!(response_result.is_ok());
 
     let request = GetRequest::new("test_delete_key");
-    let response_result = client.get(request);
+    let response_result = client.get(request).await;
     assert!(response_result.is_err());
 }
 
-#[test_case]
-fn test_enqueue_success() {
-    let mut client = get_client();
+#[async_test_case]
+async fn test_enqueue_success() {
+    let mut client = get_client().await;
     let request = EnqueueRequest::new("test_enqueue_key", "test_enqueue_value");
-    let response_result = client.enqueue(request);
+    let response_result = client.enqueue(request).await;
     debug!("{:?}", response_result);
     assert!(response_result.is_ok());
 }
 
-#[test_case]
-fn test_dequeue_success() {
-    let mut client = get_client();
+#[async_test_case]
+async fn test_dequeue_success() {
+    let mut client = get_client().await;
     let request = DequeueRequest::new("test_dequeue_key");
-    let response_result = client.dequeue(request);
+    let response_result = client.dequeue(request).await;
     assert!(response_result.is_err());
     let request = EnqueueRequest::new("test_dequeue_key", "1");
-    let response_result = client.enqueue(request);
+    let response_result = client.enqueue(request).await;
     assert!(response_result.is_ok());
     let request = EnqueueRequest::new("test_dequeue_key", "2");
-    let response_result = client.enqueue(request);
+    let response_result = client.enqueue(request).await;
     assert!(response_result.is_ok());
     let request = DequeueRequest::new("test_dequeue_key");
-    let response_result = client.dequeue(request);
+    let response_result = client.dequeue(request).await;
     assert!(response_result.is_ok());
-    assert_eq!(response_result.unwrap().value, b"1");
+    assert_eq!(response_result.unwrap().into_inner().value, b"1");
     let request = DequeueRequest::new("test_dequeue_key");
-    let response_result = client.dequeue(request);
+    let response_result = client.dequeue(request).await;
     assert!(response_result.is_ok());
-    assert_eq!(response_result.unwrap().value, b"2");
+    assert_eq!(response_result.unwrap().into_inner().value, b"2");
 }
 
-#[test_case]
-fn test_dequeue_fail() {
-    let mut client = get_client();
+#[async_test_case]
+async fn test_dequeue_fail() {
+    let mut client = get_client().await;
     let request = DequeueRequest::new("test_dequeue_key");
-    let response_result = client.dequeue(request);
+    let response_result = client.dequeue(request).await;
     assert!(response_result.is_err());
 
     let request = EnqueueRequest::new("test_dequeue_key", "1");
-    let response_result = client.enqueue(request);
+    let response_result = client.enqueue(request).await;
     assert!(response_result.is_ok());
     let request = DequeueRequest::new("test_dequeue_key");
-    let response_result = client.dequeue(request);
+    let response_result = client.dequeue(request).await;
     assert!(response_result.is_ok());
-    assert_eq!(response_result.unwrap().value, b"1");
+    assert_eq!(response_result.unwrap().into_inner().value, b"1");
     let request = DequeueRequest::new("test_dequeue_key");
-    let response_result = client.dequeue(request);
+    let response_result = client.dequeue(request).await;
     assert!(response_result.is_err());
 }
diff --git a/tests/functional/enclave/src/utils.rs b/tests/functional/enclave/src/utils.rs
index a5ead53..41ee8b6 100644
--- a/tests/functional/enclave/src/utils.rs
+++ b/tests/functional/enclave/src/utils.rs
@@ -17,7 +17,6 @@
 
 use anyhow::Result;
 use lazy_static::lazy_static;
-use std::collections::HashMap;
 use teaclave_attestation::verifier;
 use teaclave_config::build::AS_ROOT_CA_CERT;
 use teaclave_config::RuntimeConfig;
@@ -28,160 +27,192 @@
 use teaclave_proto::teaclave_management_service::*;
 use teaclave_proto::teaclave_scheduler_service::*;
 use teaclave_proto::teaclave_storage_service::*;
-use teaclave_rpc::config::SgxTrustedTlsClientConfig;
-use teaclave_rpc::endpoint::Endpoint;
+use teaclave_rpc::transport::{Channel, ClientTlsConfig, Uri};
+use teaclave_rpc::CredentialService;
 use teaclave_types::*;
 
 macro_rules! impl_get_internal_service_client_fn {
-    ($service_name:ident, $fn_name:ident, $return:ident) => {
-        pub(crate) fn $fn_name(username: &str) -> $return {
+    ($service_name:ident, $fn_name:ident, $return:ty) => {
+        pub(crate) async fn $fn_name(username: &str) -> $return {
             let runtime_config = RuntimeConfig::from_toml("runtime.config.toml").expect("runtime");
             let address = runtime_config
                 .internal_endpoints
                 .$service_name
                 .advertised_address;
-            let channel = Endpoint::new(&address).connect().unwrap();
-            let metadata = hashmap!(
-                "id" => username,
-                "token" => "",
-                "role" => "PlatformAdmin"
-            );
-            $return::new_with_metadata(channel, metadata).unwrap()
+            let dst = address.parse::<Uri>().unwrap();
+            let dst = if dst.scheme().is_none() {
+                format!("https://{}", address).parse().unwrap()
+            } else {
+                dst
+            };
+            let endpoint = Channel::builder(dst);
+            let tls_config = teaclave_rpc::config::SgxTrustedTlsClientConfig::new().into();
+            let channel = endpoint
+                .tls_config(tls_config)
+                .unwrap()
+                .connect()
+                .await
+                .unwrap();
+            let cred =
+                teaclave_rpc::UserCredential::with_role(username, "", UserRole::PlatformAdmin);
+            <$return>::new(teaclave_rpc::InterceptedService::new(channel, cred))
         }
     };
 }
 
-impl_get_internal_service_client_fn!(management, get_management_client, TeaclaveManagementClient);
+impl_get_internal_service_client_fn!(
+    management,
+    get_management_client,
+    TeaclaveManagementClient<CredentialService>
+);
 impl_get_internal_service_client_fn!(
     scheduler,
     get_scheduler_client_internal,
-    TeaclaveSchedulerClient
+    TeaclaveSchedulerClient<CredentialService>
 );
-impl_get_internal_service_client_fn!(storage, get_storage_client_internal, TeaclaveStorageClient);
+impl_get_internal_service_client_fn!(
+    storage,
+    get_storage_client_internal,
+    TeaclaveStorageClient<CredentialService>
+);
 impl_get_internal_service_client_fn!(
     access_control,
     get_access_control_client_internal,
-    TeaclaveAccessControlClient
+    TeaclaveAccessControlClient<CredentialService>
 );
 
-pub fn get_scheduler_client() -> TeaclaveSchedulerClient {
-    get_scheduler_client_internal("mock_user")
+pub async fn get_scheduler_client() -> TeaclaveSchedulerClient<CredentialService> {
+    get_scheduler_client_internal("mock_user").await
 }
 
-pub fn get_storage_client() -> TeaclaveStorageClient {
-    get_storage_client_internal("mock_user")
+pub async fn get_storage_client() -> TeaclaveStorageClient<CredentialService> {
+    get_storage_client_internal("mock_user").await
 }
 
-pub fn get_access_control_client() -> TeaclaveAccessControlClient {
-    get_access_control_client_internal("mock_user")
+pub async fn get_access_control_client() -> TeaclaveAccessControlClient<CredentialService> {
+    get_access_control_client_internal("mock_user").await
 }
 
 pub const CONFIG_FILE: &str = "runtime.config.toml";
-pub const AUTH_SERVICE_ADDR: &str = "localhost:7776";
-pub const FRONTEND_SERVICE_ADDR: &str = "localhost:7777";
+pub const AUTH_SERVICE_ADDR: &str = "https://localhost:7776";
+pub const FRONTEND_SERVICE_ADDR: &str = "https://localhost:7777";
 
 lazy_static! {
     static ref ENCLAVE_INFO: EnclaveInfo = {
         let runtime_config = RuntimeConfig::from_toml(CONFIG_FILE).expect("runtime config");
         EnclaveInfo::from_bytes(&runtime_config.audit.enclave_info_bytes)
     };
-    static ref ADMIN_CREDENTIAL: UserCredential = {
-        let mut api_client =
-            create_authentication_api_client(shared_enclave_info(), AUTH_SERVICE_ADDR).unwrap();
-        login(&mut api_client, "admin", "teaclave").unwrap()
-    };
+}
+
+pub async fn get_api_client_with_admin_credential(
+) -> TeaclaveAuthenticationApiClient<CredentialService> {
+    create_authentication_api_client_with_credential(
+        shared_enclave_info(),
+        AUTH_SERVICE_ADDR,
+        "admin",
+        "teaclave",
+    )
+    .await
+    .unwrap()
 }
 
 pub fn shared_enclave_info() -> &'static EnclaveInfo {
     &ENCLAVE_INFO
 }
 
-pub fn shared_admin_credential() -> &'static UserCredential {
-    &ADMIN_CREDENTIAL
-}
-
 pub fn create_client_config(
     enclave_info: &EnclaveInfo,
     service_name: &str,
-) -> Result<SgxTrustedTlsClientConfig> {
+) -> Result<ClientTlsConfig> {
     let enclave_attr = enclave_info
         .get_enclave_attr(service_name)
         .expect("enclave attr");
-    let config = SgxTrustedTlsClientConfig::new().attestation_report_verifier(
-        vec![enclave_attr],
-        AS_ROOT_CA_CERT,
-        verifier::universal_quote_verifier,
-    );
+    let config = teaclave_rpc::config::SgxTrustedTlsClientConfig::new()
+        .attestation_report_verifier(
+            vec![enclave_attr],
+            AS_ROOT_CA_CERT,
+            verifier::universal_quote_verifier,
+        )
+        .into();
     Ok(config)
 }
 
-pub fn create_frontend_client(
+pub async fn create_frontend_client(
     enclave_info: &EnclaveInfo,
     service_addr: &str,
     cred: UserCredential,
-) -> Result<TeaclaveFrontendClient> {
+) -> Result<TeaclaveFrontendClient<CredentialService>> {
     let tls_config = create_client_config(enclave_info, "teaclave_frontend_service")?;
-    let channel = Endpoint::new(service_addr).config(tls_config).connect()?;
-
-    let mut metadata = HashMap::new();
-    metadata.insert("id".to_string(), cred.id);
-    metadata.insert("token".to_string(), cred.token);
-
-    let client = TeaclaveFrontendClient::new_with_metadata(channel, metadata)?;
+    let endpoint = Channel::builder(service_addr.parse::<Uri>()?);
+    let channel = endpoint
+        .tls_config(tls_config)
+        .unwrap()
+        .connect()
+        .await
+        .unwrap();
+    let cred = teaclave_rpc::UserCredential::new(cred.id, cred.token);
+    let client = TeaclaveFrontendClient::with_interceptor(channel, cred);
     Ok(client)
 }
 
-pub fn create_authentication_api_client(
+pub async fn create_authentication_api_client(
     enclave_info: &EnclaveInfo,
     service_addr: &str,
-) -> Result<TeaclaveAuthenticationApiClient> {
+) -> Result<TeaclaveAuthenticationApiClient<CredentialService>> {
     let tls_config = create_client_config(enclave_info, "teaclave_authentication_service")?;
-    let channel = Endpoint::new(service_addr).config(tls_config).connect()?;
-
-    let client = TeaclaveAuthenticationApiClient::new(channel)?;
+    let endpoint = Channel::builder(service_addr.parse::<Uri>()?);
+    let channel = endpoint.tls_config(tls_config).unwrap().connect_lazy();
+    let client = TeaclaveAuthenticationApiClient::with_interceptor(
+        channel,
+        teaclave_rpc::UserCredential::default(),
+    );
     Ok(client)
 }
 
-pub fn create_authentication_api_client_with_credential(
+pub async fn create_authentication_api_client_with_credential(
     enclave_info: &EnclaveInfo,
     service_addr: &str,
-    cred: &UserCredential,
-) -> Result<TeaclaveAuthenticationApiClient> {
+    username: &str,
+    password: &str,
+) -> Result<TeaclaveAuthenticationApiClient<CredentialService>> {
     let tls_config = create_client_config(enclave_info, "teaclave_authentication_service")?;
-    let channel = Endpoint::new(service_addr).config(tls_config).connect()?;
+    let endpoint = Channel::builder(service_addr.parse::<Uri>()?);
+    let channel = endpoint
+        .tls_config(tls_config)
+        .unwrap()
+        .connect()
+        .await
+        .unwrap();
 
-    let mut metadata = HashMap::new();
-    metadata.insert("id".to_string(), cred.id.to_owned());
-    metadata.insert("token".to_string(), cred.token.to_owned());
-    let client = TeaclaveAuthenticationApiClient::new_with_metadata(channel, metadata)?;
+    let mut client = TeaclaveAuthenticationApiClient::new(channel.clone());
+    let request = UserLoginRequest::new(username, password);
+    let token = client.user_login(request).await?.into_inner().token;
+    let cred = teaclave_rpc::UserCredential::new(username, token);
+    let client = TeaclaveAuthenticationApiClient::with_interceptor(channel, cred);
     Ok(client)
 }
 
-pub fn register_new_account(
-    api_client: &mut TeaclaveAuthenticationApiClient,
+pub async fn register_new_account(
+    api_client: &mut TeaclaveAuthenticationApiClient<CredentialService>,
     username: &str,
     password: &str,
     role: &str,
     attribute: &str,
 ) -> Result<()> {
     let request = UserRegisterRequest::new(username, password, role, attribute);
-    let response = api_client.user_register(request)?;
-
+    let response = api_client.user_register(request).await;
     log::debug!("User register: {:?}", response);
-
     Ok(())
 }
 
-pub fn login(
-    api_client: &mut TeaclaveAuthenticationApiClient,
+pub async fn login(
+    api_client: &mut TeaclaveAuthenticationApiClient<CredentialService>,
     username: &str,
     password: &str,
 ) -> Result<UserCredential> {
     let request = UserLoginRequest::new(username, password);
-    let response = api_client.user_login(request)?;
-
+    let response = api_client.user_login(request).await?.into_inner();
     log::debug!("User login: {:?}", response);
-
     Ok(UserCredential::new(username, response.token))
 }
 
@@ -192,17 +223,13 @@
 
 pub const TEST_PASSWORD: &str = "test_password";
 
-pub fn setup() {
+pub async fn setup() {
     // Register user for the first time
-    let mut api_client = create_authentication_api_client_with_credential(
-        shared_enclave_info(),
-        AUTH_SERVICE_ADDR,
-        shared_admin_credential(),
-    )
-    .unwrap();
+    let mut api_client = get_api_client_with_admin_credential().await;
 
     // Ignore error if register failed.
     for uname in vec![USERNAME, USERNAME1, USERNAME2, USERNAME3].iter() {
-        let _ = register_new_account(&mut api_client, uname, TEST_PASSWORD, "PlatformAdmin", "");
+        let _ =
+            register_new_account(&mut api_client, uname, TEST_PASSWORD, "PlatformAdmin", "").await;
     }
 }
diff --git a/tests/integration/enclave/Cargo.toml b/tests/integration/enclave/Cargo.toml
index d289618..25beace 100644
--- a/tests/integration/enclave/Cargo.toml
+++ b/tests/integration/enclave/Cargo.toml
@@ -30,11 +30,7 @@
 [features]
 default = []
 mesalock_sgx = [
-  "teaclave_attestation/mesalock_sgx",
-  "teaclave_proto/mesalock_sgx",
   "teaclave_binder/mesalock_sgx",
-  "teaclave_config/mesalock_sgx",
-  "teaclave_rpc/mesalock_sgx",
   "teaclave_service_enclave_utils/mesalock_sgx",
   "teaclave_types/mesalock_sgx",
   "teaclave_crypto/mesalock_sgx",
@@ -49,20 +45,14 @@
 anyhow      = { version = "1.0.26" }
 serde       = { version = "1.0.92" }
 serde_json  = { version = "1.0.39" }
-thiserror   = { version = "1.0.9" }
 rand        = { version = "0.8.5" }
-rustls      = { version = "0.19.0", features = ["dangerous_configuration"] }
 
 rusty-leveldb = { path = "../../../common/rusty_leveldb_sgx", default-features = false, optional = true }
 
-teaclave_attestation           = { path = "../../../attestation" }
-teaclave_config                = { path = "../../../config" }
 teaclave_binder                = { path = "../../../binder" }
-teaclave_rpc                   = { path = "../../../rpc" }
 teaclave_service_enclave_utils = { path = "../../../services/utils/service_enclave_utils" }
 teaclave_types                 = { path = "../../../types" }
 teaclave_crypto                = { path = "../../../crypto" }
-teaclave_proto                 = { path = "../../../services/proto" }
 teaclave_worker                = { path = "../../../worker" }
 teaclave_test_utils            = { path = "../../../tests/utils" }
 
diff --git a/tests/integration/enclave/src/lib.rs b/tests/integration/enclave/src/lib.rs
index f920ffc..ce09fbf 100644
--- a/tests/integration/enclave/src/lib.rs
+++ b/tests/integration/enclave/src/lib.rs
@@ -29,16 +29,11 @@
 use teaclave_types::TeeServiceResult;
 
 mod rusty_leveldb_sgx;
-mod teaclave_rpc;
 mod teaclave_worker;
 
 #[handle_ecall]
 fn handle_run_test(_: &RunTestInput) -> TeeServiceResult<RunTestOutput> {
-    let ret = check_all_passed!(
-        rusty_leveldb_sgx::run_tests(),
-        teaclave_rpc::run_tests(),
-        teaclave_worker::run_tests()
-    );
+    let ret = check_all_passed!(rusty_leveldb_sgx::run_tests(), teaclave_worker::run_tests());
     assert!(ret);
 
     Ok(RunTestOutput)
diff --git a/tests/integration/enclave/src/teaclave_rpc.rs b/tests/integration/enclave/src/teaclave_rpc.rs
deleted file mode 100644
index 1574ba2..0000000
--- a/tests/integration/enclave/src/teaclave_rpc.rs
+++ /dev/null
@@ -1,141 +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::Result;
-use rustls::internal::pemfile;
-use serde::{Deserialize, Serialize};
-use std::io;
-use std::untrusted::fs;
-use teaclave_rpc::channel::*;
-use teaclave_rpc::config::*;
-use teaclave_rpc::endpoint::*;
-use teaclave_rpc::server::*;
-use teaclave_rpc::*;
-use teaclave_types::TeaclaveServiceResponseError;
-use teaclave_types::TeaclaveServiceResponseResult;
-
-const END_FULLCHAIN: &str = "./fixtures/end_fullchain.pem";
-const END_KEY: &str = "./fixtures/end_key.pem";
-
-#[derive(Serialize, Deserialize, Debug)]
-#[serde(tag = "request", rename_all = "snake_case")]
-enum EchoRequest {
-    Say(SayRequest),
-}
-
-#[derive(Serialize, Deserialize, Debug)]
-struct SayRequest {
-    message: String,
-}
-
-#[derive(Serialize, Deserialize, Debug)]
-#[serde(tag = "response", rename_all = "snake_case")]
-enum EchoResponse {
-    Say(SayResponse),
-}
-
-#[derive(Serialize, Deserialize, Debug)]
-struct SayResponse {
-    message: String,
-}
-
-#[derive(Clone)]
-struct EchoService;
-
-impl TeaclaveService<EchoRequest, EchoResponse> for EchoService {
-    fn handle_request(
-        &self,
-        request: teaclave_rpc::Request<EchoRequest>,
-    ) -> TeaclaveServiceResponseResult<EchoResponse> {
-        debug!("handle request: {:?}", request);
-        let message = match request.message {
-            EchoRequest::Say(s) => s.message,
-        };
-        Ok(EchoResponse::Say(SayResponse { message }))
-    }
-}
-
-struct EchoClient {
-    channel: SgxTrustedTlsChannel<EchoRequest, EchoResponse>,
-}
-
-impl EchoClient {
-    fn new(channel: SgxTrustedTlsChannel<EchoRequest, EchoResponse>) -> Result<Self> {
-        Ok(Self { channel })
-    }
-
-    fn say(&mut self, request: SayRequest) -> TeaclaveServiceResponseResult<SayResponse> {
-        let request = EchoRequest::Say(request);
-        let request = Request {
-            metadata: std::collections::HashMap::<String, String>::new(),
-            message: request,
-        };
-        let response = match self.channel.invoke(request) {
-            Ok(response_result) => response_result,
-            Err(_) => {
-                return Err(TeaclaveServiceResponseError::InternalError(
-                    "internal".to_string(),
-                ));
-            }
-        };
-        match response {
-            EchoResponse::Say(r) => Ok(r),
-        }
-    }
-}
-
-pub fn run_tests() -> bool {
-    use teaclave_test_utils::*;
-
-    start_echo_service();
-
-    run_tests!(echo_success)
-}
-
-fn start_echo_service() {
-    use std::thread;
-    use std::time::Duration;
-    thread::spawn(move || {
-        let cert = pemfile::certs(&mut io::BufReader::new(
-            fs::File::open(END_FULLCHAIN).unwrap(),
-        ))
-        .unwrap();
-        let private_key =
-            &pemfile::pkcs8_private_keys(&mut io::BufReader::new(fs::File::open(END_KEY).unwrap()))
-                .unwrap()[0];
-        let addr = "127.0.0.1:12345".parse().unwrap();
-        let config = SgxTrustedTlsServerConfig::new()
-            .server_cert(cert[0].as_ref(), &private_key.0)
-            .unwrap();
-        let mut server = SgxTrustedTlsServer::<EchoResponse, EchoRequest>::new(addr, config);
-        server.start(EchoService).unwrap();
-    });
-    thread::sleep(Duration::from_secs(3));
-}
-
-fn echo_success() {
-    let channel = Endpoint::new("localhost:12345").connect().unwrap();
-    let mut client = EchoClient::new(channel).unwrap();
-    let request = SayRequest {
-        message: "Hello, World!".to_string(),
-    };
-    let response_result = client.say(request);
-    debug!("{:?}", response_result);
-
-    assert!(response_result.is_ok());
-    assert!(response_result.unwrap().message == "Hello, World!");
-}
diff --git a/tests/utils/Cargo.toml b/tests/utils/Cargo.toml
index e0495de..4e6dad4 100644
--- a/tests/utils/Cargo.toml
+++ b/tests/utils/Cargo.toml
@@ -30,3 +30,5 @@
 [dependencies]
 inventory   = { version = "0.1.6" }
 teaclave_test_utils_proc_macro = { path = "./proc_macro" }
+tokio       = { version = "1.0", features = ["rt-multi-thread", "time", "macros"] }
+futures     = { version = "0.3" }
\ No newline at end of file
diff --git a/tests/utils/proc_macro/Cargo.toml b/tests/utils/proc_macro/Cargo.toml
index 3fdfcbd..505f121 100644
--- a/tests/utils/proc_macro/Cargo.toml
+++ b/tests/utils/proc_macro/Cargo.toml
@@ -26,5 +26,5 @@
 
 [dependencies]
 proc-macro2 = "1.0"
-quote = "1.0"
-syn = { version = "1.0", features = ["full"] }
\ No newline at end of file
+quote       = "1.0"
+syn         = { version = "1.0", features = ["full"] }
diff --git a/tests/utils/proc_macro/src/lib.rs b/tests/utils/proc_macro/src/lib.rs
index 627459d..87d976d 100644
--- a/tests/utils/proc_macro/src/lib.rs
+++ b/tests/utils/proc_macro/src/lib.rs
@@ -16,12 +16,11 @@
 // under the License.
 
 extern crate proc_macro;
+use proc_macro::TokenStream;
 use quote::quote;
 use syn::parse_macro_input;
 use syn::ItemFn;
 
-use proc_macro::TokenStream;
-
 #[proc_macro_attribute]
 pub fn test_case(_attr: TokenStream, input: TokenStream) -> TokenStream {
     let f = parse_macro_input!(input as ItemFn);
@@ -39,3 +38,37 @@
 
     q.into()
 }
+
+#[proc_macro_attribute]
+pub fn async_test_case(_args: TokenStream, item: TokenStream) -> TokenStream {
+    let input = syn::parse_macro_input!(item as syn::ItemFn);
+    let name = &input.sig.ident;
+
+    if input.sig.asyncness.is_none() {
+        let msg = "the async keyword is missing from the function declaration";
+        return syn::Error::new_spanned(input.sig.fn_token, msg)
+            .to_compile_error()
+            .into();
+    } else if !input.sig.inputs.is_empty() {
+        let msg = "the test function cannot accept arguments";
+        return syn::Error::new_spanned(&input.sig.inputs, msg)
+            .to_compile_error()
+            .into();
+    } else if input.sig.output != syn::ReturnType::Default {
+        let msg = "the test function cannot return outputs";
+        return syn::Error::new_spanned(input.sig.output, msg)
+            .to_compile_error()
+            .into();
+    }
+
+    let result = quote!(
+        #input
+
+        inventory::submit!(
+            teaclave_test_utils::AsyncTestCase(
+                concat!(module_path!(), "::", stringify!(#name)).to_string(),
+                || async move {#name().await }.boxed()
+        )
+    ););
+    result.into()
+}
diff --git a/tests/utils/src/lib.rs b/tests/utils/src/lib.rs
index f63aca6..85a96d7 100644
--- a/tests/utils/src/lib.rs
+++ b/tests/utils/src/lib.rs
@@ -15,20 +15,22 @@
 // specific language governing permissions and limitations
 // under the License.
 
+pub use futures::FutureExt;
+
+use futures::future::BoxFuture;
 use std::string::String;
 use std::vec::Vec;
-
-pub use teaclave_test_utils_proc_macro::test_case;
-
+pub use teaclave_test_utils_proc_macro::{async_test_case, test_case};
 pub struct TestCase(pub String, pub fn() -> ());
+pub struct AsyncTestCase(pub String, pub fn() -> BoxFuture<'static, ()>);
 
 inventory::collect!(TestCase);
+inventory::collect!(AsyncTestCase);
 
 use std::time::Instant;
 #[cfg(feature = "mesalock_sgx")]
 #[allow(unused_imports)]
 use std::untrusted::time::InstantEx;
-
 #[macro_export]
 macro_rules! run_inventory_tests {
     ($predicate:expr) => {{
@@ -42,6 +44,11 @@
             }
         }
 
+        for t in inventory::iter::<teaclave_test_utils::AsyncTestCase>.into_iter() {
+            if $predicate(&t.0) {
+                teaclave_test_utils::async_test(&mut ntestcases, &mut failurecases, t.1, &t.0);
+            }
+        }
         teaclave_test_utils::test_end(ntestcases, failurecases)
     }};
     () => {
@@ -96,6 +103,22 @@
     }
 }
 
+#[macro_export]
+macro_rules! run_async_tests {
+    (
+        $($f : expr),* $(,)?
+    ) => {
+        {
+            teaclave_test_utils::test_start();
+            let mut ntestcases : u64 = 0u64;
+            let mut failurecases : Vec<String> = Vec::new();
+            use $crate::FutureExt;
+            $(teaclave_test_utils::async_test(&mut ntestcases, &mut failurecases, || async {$f().await}.boxed(),stringify!($f));)*
+            teaclave_test_utils::test_end(ntestcases, failurecases)
+        }
+    }
+}
+
 pub fn test_start() {
     println!("\nstart running tests");
 }
@@ -130,17 +153,12 @@
 }
 
 #[allow(clippy::print_literal)]
-pub fn test<F, R>(ncases: &mut u64, failurecases: &mut Vec<String>, f: F, name: &str)
+fn do_test<F>(f: F, ncases: &mut u64, failurecases: &mut Vec<String>, name: &str)
 where
-    F: FnOnce() -> R + std::panic::UnwindSafe,
+    F: FnOnce() -> f64 + std::panic::UnwindSafe,
 {
     *ncases += 1;
-    let t = || -> f64 {
-        let before = Instant::now();
-        f();
-        before.elapsed().as_secs_f64()
-    };
-    match std::panic::catch_unwind(t) {
+    match std::panic::catch_unwind(f) {
         Ok(elapsed) => {
             println!("{} {} ... {}!", "testing", name, "\x1B[1;32mok\x1B[0m");
             if elapsed < 0.5 {
@@ -155,3 +173,31 @@
         }
     }
 }
+
+pub fn test<F, R>(ncases: &mut u64, failurecases: &mut Vec<String>, f: F, name: &str)
+where
+    F: FnOnce() -> R + std::panic::UnwindSafe,
+{
+    let t = || -> f64 {
+        let before = Instant::now();
+        f();
+        before.elapsed().as_secs_f64()
+    };
+    do_test(t, ncases, failurecases, name)
+}
+
+pub fn async_test<F>(ncases: &mut u64, failurecases: &mut Vec<String>, f: F, name: &str)
+where
+    F: FnOnce() -> BoxFuture<'static, ()> + std::panic::UnwindSafe,
+{
+    let t = || -> f64 {
+        let before = Instant::now();
+        let rt = tokio::runtime::Builder::new_current_thread()
+            .enable_all()
+            .build()
+            .unwrap();
+        rt.block_on(f());
+        before.elapsed().as_secs_f64()
+    };
+    do_test(t, ncases, failurecases, name)
+}
diff --git a/types/Cargo.toml b/types/Cargo.toml
index 1fc0900..aadc0d4 100644
--- a/types/Cargo.toml
+++ b/types/Cargo.toml
@@ -45,6 +45,7 @@
 toml         = { version = "0.5.3" }
 ring         = { version = "0.16.5" }
 thiserror    = { version = "1.0.9" }
+tonic        = { version = "0.6.1", features = ["tls", "compression"]  }
 url          = { version = "2.1.1", features = ["serde"]}
 uuid         = { version = "0.8.1", features = ["v4", "v5", "serde"] }
 
diff --git a/types/src/error.rs b/types/src/error.rs
index c36a53e..65d9b69 100644
--- a/types/src/error.rs
+++ b/types/src/error.rs
@@ -68,21 +68,8 @@
 
 pub type TeeServiceResult<T> = std::result::Result<T, TeeServiceError>;
 
-#[derive(Error, Debug, Serialize, Deserialize, PartialEq)]
-#[serde(rename_all = "snake_case")]
-pub enum TeaclaveServiceResponseError {
-    #[error("Request error: {0}")]
-    RequestError(String),
-    #[error("Connection error: {0}")]
-    ConnectionError(String),
-    #[error("Internal error: {0}")]
-    InternalError(String),
-}
+pub type TeaclaveServiceResponseResult<T> = std::result::Result<tonic::Response<T>, tonic::Status>;
 
-impl From<anyhow::Error> for TeaclaveServiceResponseError {
-    fn from(error: anyhow::Error) -> Self {
-        TeaclaveServiceResponseError::RequestError(error.to_string())
-    }
+pub fn tonic_error<T: std::fmt::Debug>(err: T) -> tonic::Status {
+    tonic::Status::internal(format!("{:?}", err))
 }
-
-pub type TeaclaveServiceResponseResult<T> = std::result::Result<T, TeaclaveServiceResponseError>;
diff --git a/worker/src/worker.rs b/worker/src/worker.rs
index 5a15ffb..8a81f89 100644
--- a/worker/src/worker.rs
+++ b/worker/src/worker.rs
@@ -18,10 +18,8 @@
 use std::collections::HashMap;
 use std::format;
 
-use teaclave_types::{Executor, ExecutorType, StagedFiles, StagedFunction};
-
-use teaclave_executor::*;
 use teaclave_runtime::DefaultRuntime;
+use teaclave_types::{Executor, ExecutorType, StagedFiles, StagedFunction};
 use teaclave_types::{TeaclaveExecutor, TeaclaveRuntime};
 
 type BoxedTeaclaveExecutor = Box<dyn TeaclaveExecutor + Send + Sync>;
@@ -51,16 +49,16 @@
         // Register supported executors
         #[cfg(all(executor_mesapy, not(feature = "app")))]
         worker.register_executor((ExecutorType::Python, Executor::MesaPy), || {
-            Box::<MesaPy>::default()
+            Box::<teaclave_executor::MesaPy>::default()
         });
         #[cfg(executor_builtin)]
         worker.register_executor((ExecutorType::Builtin, Executor::Builtin), || {
-            Box::<BuiltinFunctionExecutor>::default()
+            Box::<teaclave_executor::BuiltinFunctionExecutor>::default()
         });
         #[cfg(executor_wamr)]
         worker.register_executor(
             (ExecutorType::WAMicroRuntime, Executor::WAMicroRuntime),
-            || Box::<WAMicroRuntime>::default(),
+            || Box::<teaclave_executor::WAMicroRuntime>::default(),
         );
 
         worker