You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@teaclave.apache.org by ms...@apache.org on 2020/06/09 02:17:22 UTC

[incubator-teaclave] 01/02: Add docs for Client SDK in Python

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

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

commit bea1ec21b9887ac914b05fb942e6ad7089b2d4e2
Author: Mingshen Sun <bo...@mssun.me>
AuthorDate: Mon Jun 8 16:44:11 2020 -0700

    Add docs for Client SDK in Python
---
 examples/python/builtin_echo.py           |  15 +-
 examples/python/builtin_gbdt_train.py     |  46 +---
 examples/python/builtin_online_decrypt.py |  15 +-
 examples/python/mesapy_echo.py            |  15 +-
 sdk/python/teaclave.py                    | 359 +++++++++++++++++++++---------
 5 files changed, 290 insertions(+), 160 deletions(-)

diff --git a/examples/python/builtin_echo.py b/examples/python/builtin_echo.py
index d9569b2..f60fd9a 100644
--- a/examples/python/builtin_echo.py
+++ b/examples/python/builtin_echo.py
@@ -15,10 +15,9 @@ class BuiltinEchoExample:
         self.user_password = user_password
 
     def echo(self, message="Hello, Teaclave!"):
-        channel = AuthenticationService(AUTHENTICATION_SERVICE_ADDRESS,
-                                        AS_ROOT_CA_CERT_PATH,
-                                        ENCLAVE_INFO_PATH).connect()
-        client = AuthenticationClient(channel)
+        client = AuthenticationService(
+            AUTHENTICATION_SERVICE_ADDRESS, AS_ROOT_CA_CERT_PATH,
+            ENCLAVE_INFO_PATH).connect().get_client()
 
         print("[+] registering user")
         client.user_register(self.user_id, self.user_password)
@@ -26,11 +25,11 @@ class BuiltinEchoExample:
         print("[+] login")
         token = client.user_login(self.user_id, self.user_password)
 
-        channel = FrontendService(FRONTEND_SERVICE_ADDRESS,
-                                  AS_ROOT_CA_CERT_PATH,
-                                  ENCLAVE_INFO_PATH).connect()
+        client = FrontendService(FRONTEND_SERVICE_ADDRESS,
+                                 AS_ROOT_CA_CERT_PATH,
+                                 ENCLAVE_INFO_PATH).connect().get_client()
         metadata = {"id": self.user_id, "token": token}
-        client = FrontendClient(channel, metadata)
+        client.metadata = metadata
 
         print("[+] registering function")
         function_id = client.register_function(
diff --git a/examples/python/builtin_gbdt_train.py b/examples/python/builtin_gbdt_train.py
index 7d72715..e565ba1 100644
--- a/examples/python/builtin_gbdt_train.py
+++ b/examples/python/builtin_gbdt_train.py
@@ -3,46 +3,22 @@
 import sys
 
 from teaclave import (AuthenticationService, FrontendService,
-                      AuthenticationClient, FrontendClient)
+                      AuthenticationClient, FrontendClient, FunctionInput,
+                      FunctionOutput, OwnerList, DataMap)
 from utils import (AUTHENTICATION_SERVICE_ADDRESS, FRONTEND_SERVICE_ADDRESS,
                    AS_ROOT_CA_CERT_PATH, ENCLAVE_INFO_PATH, USER_ID,
                    USER_PASSWORD)
 
 
-class FunctionInput:
-    def __init__(self, name, description):
-        self.name = name
-        self.description = description
-
-
-class FunctionOutput:
-    def __init__(self, name, description):
-        self.name = name
-        self.description = description
-
-
-class OwnerList:
-    def __init__(self, data_name, uids):
-        self.data_name = data_name
-        self.uids = uids
-
-
-class DataList:
-    def __init__(self, data_name, data_id):
-        self.data_name = data_name
-        self.data_id = data_id
-
-
 class BuiltinGbdtExample:
     def __init__(self, user_id, user_password):
         self.user_id = user_id
         self.user_password = user_password
 
     def gbdt(self):
-        channel = AuthenticationService(AUTHENTICATION_SERVICE_ADDRESS,
-                                        AS_ROOT_CA_CERT_PATH,
-                                        ENCLAVE_INFO_PATH).connect()
-        client = AuthenticationClient(channel)
+        client = AuthenticationService(
+            AUTHENTICATION_SERVICE_ADDRESS, AS_ROOT_CA_CERT_PATH,
+            ENCLAVE_INFO_PATH).connect().get_client()
 
         print("[+] registering user")
         client.user_register(self.user_id, self.user_password)
@@ -50,11 +26,11 @@ class BuiltinGbdtExample:
         print("[+] login")
         token = client.user_login(self.user_id, self.user_password)
 
-        channel = FrontendService(FRONTEND_SERVICE_ADDRESS,
-                                  AS_ROOT_CA_CERT_PATH,
-                                  ENCLAVE_INFO_PATH).connect()
+        client = FrontendService(FRONTEND_SERVICE_ADDRESS,
+                                 AS_ROOT_CA_CERT_PATH,
+                                 ENCLAVE_INFO_PATH).connect().get_client()
         metadata = {"id": self.user_id, "token": token}
-        client = FrontendClient(channel, metadata)
+        client.metadata = metadata
 
         print("[+] registering function")
         function_id = client.register_function(
@@ -110,8 +86,8 @@ class BuiltinGbdtExample:
 
         print("[+] assigning data to task")
         client.assign_data_to_task(
-            task_id, [DataList("training_data", training_data_id)],
-            [DataList("trained_model", output_model_id)])
+            task_id, [DataMap("training_data", training_data_id)],
+            [DataMap("trained_model", output_model_id)])
 
         print("[+] approving task")
         client.approve_task(task_id)
diff --git a/examples/python/builtin_online_decrypt.py b/examples/python/builtin_online_decrypt.py
index d14cf7a..e660e57 100644
--- a/examples/python/builtin_online_decrypt.py
+++ b/examples/python/builtin_online_decrypt.py
@@ -16,10 +16,9 @@ class BuiltinOnlineDecryptExample:
         self.user_password = user_password
 
     def decrypt(self, key, nonce, encrypted_data, algorithm):
-        channel = AuthenticationService(AUTHENTICATION_SERVICE_ADDRESS,
-                                        AS_ROOT_CA_CERT_PATH,
-                                        ENCLAVE_INFO_PATH).connect()
-        client = AuthenticationClient(channel)
+        client = AuthenticationService(
+            AUTHENTICATION_SERVICE_ADDRESS, AS_ROOT_CA_CERT_PATH,
+            ENCLAVE_INFO_PATH).connect().get_client()
 
         print("[+] registering user")
         client.user_register(self.user_id, self.user_password)
@@ -27,11 +26,11 @@ class BuiltinOnlineDecryptExample:
         print("[+] login")
         token = client.user_login(self.user_id, self.user_password)
 
-        channel = FrontendService(FRONTEND_SERVICE_ADDRESS,
-                                  AS_ROOT_CA_CERT_PATH,
-                                  ENCLAVE_INFO_PATH).connect()
+        client = FrontendService(FRONTEND_SERVICE_ADDRESS,
+                                 AS_ROOT_CA_CERT_PATH,
+                                 ENCLAVE_INFO_PATH).connect().get_client()
         metadata = {"id": self.user_id, "token": token}
-        client = FrontendClient(channel, metadata)
+        client.metadata = metadata
 
         print("[+] registering function")
         function_id = client.register_function(
diff --git a/examples/python/mesapy_echo.py b/examples/python/mesapy_echo.py
index 570adc7..3f12512 100644
--- a/examples/python/mesapy_echo.py
+++ b/examples/python/mesapy_echo.py
@@ -17,10 +17,9 @@ class MesaPyEchoExample:
     def echo(self,
              payload_file="mesapy_echo_payload.py",
              message="Hello, Teaclave!"):
-        channel = AuthenticationService(AUTHENTICATION_SERVICE_ADDRESS,
-                                        AS_ROOT_CA_CERT_PATH,
-                                        ENCLAVE_INFO_PATH).connect()
-        client = AuthenticationClient(channel)
+        client = AuthenticationService(
+            AUTHENTICATION_SERVICE_ADDRESS, AS_ROOT_CA_CERT_PATH,
+            ENCLAVE_INFO_PATH).connect().get_client()
 
         print("[+] registering user")
         client.user_register(self.user_id, self.user_password)
@@ -28,11 +27,11 @@ class MesaPyEchoExample:
         print("[+] login")
         token = client.user_login(self.user_id, self.user_password)
 
-        channel = FrontendService(FRONTEND_SERVICE_ADDRESS,
-                                  AS_ROOT_CA_CERT_PATH,
-                                  ENCLAVE_INFO_PATH).connect()
+        client = FrontendService(FRONTEND_SERVICE_ADDRESS,
+                                 AS_ROOT_CA_CERT_PATH,
+                                 ENCLAVE_INFO_PATH).connect().get_client()
         metadata = {"id": self.user_id, "token": token}
-        client = FrontendClient(channel, metadata)
+        client.metadata = metadata
 
         print("[+] registering function")
 
diff --git a/sdk/python/teaclave.py b/sdk/python/teaclave.py
index 31d0858..1da3179 100644
--- a/sdk/python/teaclave.py
+++ b/sdk/python/teaclave.py
@@ -1,4 +1,10 @@
 #!/usr/bin/env python3
+"""
+Python package `teaclave` is the client SDK for Python developers, providing
+some essential data structures, service, and client classes to establish
+trusted TLS channel and communicate with Teaclave services (e.g., the
+authentication service and frontend service) through RPC protocols.
+"""
 
 import struct
 import json
@@ -9,6 +15,8 @@ import time
 import ssl
 import socket
 
+from typing import Tuple, Dict, List, Any
+
 from cryptography import x509
 from cryptography.hazmat.backends import default_backend
 
@@ -16,83 +24,226 @@ from OpenSSL.crypto import load_certificate, FILETYPE_PEM, FILETYPE_ASN1
 from OpenSSL.crypto import X509Store, X509StoreContext
 from OpenSSL import crypto
 
+__all__ = [
+    'FrontendClient', 'FrontendService', 'AuthenticationClient',
+    'AuthenticationService', 'FunctionInput', 'FunctionOutput', 'OwnerList',
+    'DataMap'
+]
+
+Metadata = Dict[str, str]
+
+
+class FunctionInput:
+    """Function input for registering.
+
+    Args:
+        name: Name of input data.
+        description: Description of the input data.
+    """
+    def __init__(self, name: str, description: str):
+        self.name = name
+        self.description = description
+
+
+class FunctionOutput:
+    """Function output for registering.
+
+    Args:
+        name: Name of output data.
+        description: Description of the output data.
+    """
+    def __init__(self, name: str, description: str):
+        self.name = name
+        self.description = description
+
+
+class OwnerList:
+    """Defines data ownership.
+
+    Args:
+        data_name: Name of output data.
+        uids: A list of user id which own this data.
+    """
+    def __init__(self, data_name: str, uids: List[str]):
+        self.data_name = data_name
+        self.uids = uids
+
 
-class RequestEncoder(json.JSONEncoder):
-    def default(self, o):
-        return o.__dict__
+class DataMap:
+    """Assign data id to input or output data.
+
+    Args:
+        data_name: Name of output data.
+        data_id: Id for the data name.
+    """
+    def __init__(self, data_name, data_id):
+        self.data_name = data_name
+        self.data_id = data_id
+
+
+class CryptoInfo:
+    """Cryptographic information for the input/output data.
+
+    Args:
+        schema: Encryption algorithms for the input/output data.
+        key: Key for encryption and decryption, bytes in list.
+        iv: IV, bytes in list.
+    """
+    def __init__(self, schema: str, key: List[int], iv: List[int]):
+        self.schema = schema
+        self.key = key
+        self.iv = iv
 
 
 class UserRegisterReqeust:
-    def __init__(self, user_id, user_password):
+    def __init__(self, user_id: str, user_password: str):
         self.request = "user_register"
         self.id = user_id
         self.password = user_password
 
 
 class UserLoginRequest:
-    def __init__(self, user_id, user_password):
+    def __init__(self, user_id: str, user_password: str):
         self.request = "user_login"
         self.id = user_id
         self.password = user_password
 
 
-class AuthenticationClient:
-    def __init__(self, channel):
-        self.channel = channel
-
-    def user_register(self, user_id, user_password):
-        request = UserRegisterReqeust(user_id, user_password)
-        write_message(self.channel, request)
-        return read_message(self.channel)
-
-    def user_login(self, user_id, user_password):
-        request = UserLoginRequest(user_id, user_password)
-        write_message(self.channel, request)
-        response = read_message(self.channel)
-        return response["content"]["token"]
-
-
 class AuthenticationService:
-    context = ssl._create_unverified_context()
-
-    def __init__(self, address, as_root_ca_cert_path, enclave_info_path):
+    """
+    Establish trusted channel with the authentication service and provide
+    clients to send request through RPC.
+
+    Args:
+        address: The address of the remote services in tuple.
+        as_root_ca_cert_path: Root CA certification of the attestation services
+            to verify the attestation report.
+        enclave_info_path: Path of enclave info to verify the remote service in
+            the attestation report.
+    """
+    _context = ssl._create_unverified_context()
+    _channel = None
+
+    def __init__(self, address: Tuple[str, int], as_root_ca_cert_path: str,
+                 enclave_info_path: str):
         self.address = address
         self.as_root_ca_cert_path = as_root_ca_cert_path
         self.enclave_info_path = enclave_info_path
 
     def connect(self):
+        """Establish trusted connection and verify remote attestation report.
+
+        Returns:
+            AuthenticationService: The original object which can be chained
+                with other methods.
+        """
         sock = socket.create_connection(self.address)
-        channel = self.context.wrap_socket(sock,
-                                           server_hostname=self.address[0])
+        channel = self._context.wrap_socket(sock,
+                                            server_hostname=self.address[0])
         cert = channel.getpeercert(binary_form=True)
-        verify_report(self.as_root_ca_cert_path, self.enclave_info_path, cert,
-                      "authentication")
+        _verify_report(self.as_root_ca_cert_path, self.enclave_info_path, cert,
+                       "authentication")
 
-        return channel
+        self._channel = channel
 
+        return self
 
-class FrontendService:
-    context = ssl._create_unverified_context()
+    def get_client(self):
+        """Get a client of authentication service to send RPC requests.
+
+        Returns:
+            AuthenticationClient: Used for send/receive RPC requests.
+        """
+        return AuthenticationClient(self._channel)
+
+
+class AuthenticationClient:
+    """Client to communicate with the authentication service.
 
-    def __init__(self, address, as_root_ca_cert_path, enclave_info_path):
+    Args:
+        channel: Trusted TLS socket (verified with remote attestation).
+    """
+    def __init__(self, channel: ssl.SSLSocket):
+        self.channel = channel
+
+    def user_register(self, user_id: str, user_password: str):
+        """Register a new user.
+
+        Args:
+            user_id: User ID.
+            user_password: Password.
+        """
+        request = UserRegisterReqeust(user_id, user_password)
+        _write_message(self.channel, request)
+        _ = _read_message(self.channel)
+
+    def user_login(self, user_id: str, user_password: str) -> str:
+        """Login and get a session token.
+
+        Args:
+            user_id: User ID.
+            user_password: Password.
+
+        Returns:
+            str: User login token.
+        """
+        request = UserLoginRequest(user_id, user_password)
+        _write_message(self.channel, request)
+        response = _read_message(self.channel)
+        return response["content"]["token"]
+
+
+class FrontendService:
+    """Establish trusted channel with the frontend service and provide
+    clients to send request through RPC.
+
+    Args:
+        address: The address of the remote services in tuple.
+        as_root_ca_cert_path: Root CA certification of the attestation services
+            to verify the attestation report.
+        enclave_info_path: Path of enclave info to verify the remote service in
+            the attestation report.
+    """
+    _context = ssl._create_unverified_context()
+    _channel = None
+
+    def __init__(self, address: Tuple[str, int], as_root_ca_cert_path: str,
+                 enclave_info_path: str):
         self.address = address
         self.as_root_ca_cert_path = as_root_ca_cert_path
         self.enclave_info_path = enclave_info_path
 
     def connect(self):
+        """Establish trusted connection and verify remote attestation report.
+
+        Returns:
+            FrontendService: The original object which can be chained
+                with other methods.
+        """
         sock = socket.create_connection(self.address)
-        channel = self.context.wrap_socket(sock,
-                                           server_hostname=self.address[0])
+        channel = self._context.wrap_socket(sock,
+                                            server_hostname=self.address[0])
         cert = channel.getpeercert(binary_form=True)
-        verify_report(self.as_root_ca_cert_path, self.enclave_info_path, cert,
-                      "frontend")
+        _verify_report(self.as_root_ca_cert_path, self.enclave_info_path, cert,
+                       "frontend")
+
+        self._channel = channel
+        return self
 
-        return channel
+    def get_client(self):
+        """Get a client of frontend service to send RPC requests.
+
+        Returns:
+            FrontendClient: Used for send/receive RPC requests.
+        """
+        return FrontendClient(self._channel)
 
 
 class RegisterFunctionRequest:
-    def __init__(self, metadata, name, description, executor_type, public,
-                 payload, arguments, inputs, outputs):
+    def __init__(self, metadata: Metadata, name: str, description: str,
+                 executor_type: str, public: bool, payload: List[int],
+                 arguments: List[str], inputs: List[FunctionInput],
+                 outputs: List[FunctionOutput]):
         self.request = "register_function"
         self.metadata = metadata
         self.name = name
@@ -106,7 +257,8 @@ class RegisterFunctionRequest:
 
 
 class RegisterInputFileRequest:
-    def __init__(self, metadata, url, cmac, crypto_info):
+    def __init__(self, metadata: Metadata, url: str, cmac: str,
+                 crypto_info: CryptoInfo):
         self.request = "register_input_file"
         self.metadata = metadata
         self.url = url
@@ -115,30 +267,34 @@ class RegisterInputFileRequest:
 
 
 class RegisterOutputFileRequest:
-    def __init__(self, metadata, url, crypto_info):
+    def __init__(self, metadata: Metadata, url: str, crypto_info: CryptoInfo):
         self.request = "register_output_file"
         self.metadata = metadata
         self.url = url
         self.crypto_info = crypto_info
 
+
 class UpdateInputFileRequest:
-    def __init__(self, metadata, data_id, url):
+    def __init__(self, metadata: Metadata, data_id: str, url: str):
         self.request = "update_input_file"
         self.metadata = metadata
-        self.data_id =data_id
+        self.data_id = data_id
         self.url = url
 
 
 class UpdateOutputFileRequest:
-    def __init__(self, metadata, data_id, url):
+    def __init__(self, metadata: Metadata, data_id: str, url: str):
         self.request = "update_output_file"
         self.metadata = metadata
-        self.data_id =data_id
+        self.data_id = data_id
         self.url = url
 
+
 class CreateTaskRequest:
-    def __init__(self, metadata, function_id, function_arguments, executor,
-                 inputs_ownership, outputs_ownership):
+    def __init__(self, metadata: Metadata, function_id: str,
+                 function_arguments: Dict[str, Any], executor: str,
+                 inputs_ownership: List[OwnerList],
+                 outputs_ownership: List[OwnerList]):
         self.request = "create_task"
         self.metadata = metadata
         self.function_id = function_id
@@ -149,7 +305,8 @@ class CreateTaskRequest:
 
 
 class AssignDataRequest:
-    def __init__(self, metadata, task_id, inputs, outputs):
+    def __init__(self, metadata: Metadata, task_id: str, inputs: List[DataMap],
+                 outputs: List[DataMap]):
         self.request = "assign_data"
         self.metadata = metadata
         self.task_id = task_id
@@ -158,106 +315,102 @@ class AssignDataRequest:
 
 
 class ApproveTaskRequest:
-    def __init__(self, metadata, task_id):
+    def __init__(self, metadata: Metadata, task_id: str):
         self.request = "approve_task"
         self.metadata = metadata
         self.task_id = task_id
 
 
 class InvokeTaskRequest:
-    def __init__(self, metadata, task_id):
+    def __init__(self, metadata: Metadata, task_id: str):
         self.request = "invoke_task"
         self.metadata = metadata
         self.task_id = task_id
 
 
 class GetTaskRequest:
-    def __init__(self, metadata, task_id):
+    def __init__(self, metadata: Metadata, task_id: str):
         self.request = "get_task"
         self.metadata = metadata
         self.task_id = task_id
 
 
-class TeaclaveFile128Key:
-    def __init__(self, schema, key, iv):
-        self.schema = schema
-        self.key = key
-        self.iv = iv
-
-
 class FrontendClient:
-    def __init__(self, channel, metadata):
+    def __init__(self, channel: ssl.SSLSocket, metadata: Metadata = None):
         self.channel = channel
         self.metadata = metadata
 
     def register_function(self,
-                          name,
-                          description,
-                          executor_type,
-                          public=True,
-                          payload=[],
-                          arguments=[],
-                          inputs=[],
-                          outputs=[]):
+                          name: str,
+                          description: str,
+                          executor_type: str,
+                          public: bool = True,
+                          payload: List[int] = [],
+                          arguments: List[str] = [],
+                          inputs: List[FunctionInput] = [],
+                          outputs: List[FunctionOutput] = []):
         request = RegisterFunctionRequest(self.metadata, name, description,
                                           executor_type, public, payload,
                                           arguments, inputs, outputs)
-        write_message(self.channel, request)
-        response = read_message(self.channel)
+        _write_message(self.channel, request)
+        response = _read_message(self.channel)
         return response["content"]["function_id"]
 
-    def register_input_file(self, url, schema, key, iv, cmac):
+    def register_input_file(self, url: str, schema: str, key: List[int],
+                            iv: List[int], cmac: str):
         request = RegisterInputFileRequest(self.metadata, url, cmac,
-                                           TeaclaveFile128Key(schema, key, iv))
-        write_message(self.channel, request)
-        response = read_message(self.channel)
+                                           CryptoInfo(schema, key, iv))
+        _write_message(self.channel, request)
+        response = _read_message(self.channel)
         return response["content"]["data_id"]
 
-    def register_output_file(self, url, schema, key, iv):
-        request = RegisterOutputFileRequest(
-            self.metadata, url, TeaclaveFile128Key(schema, key, iv))
-        write_message(self.channel, request)
-        response = read_message(self.channel)
+    def register_output_file(self, url: str, schema: str, key: List[int],
+                             iv: List[int]):
+        request = RegisterOutputFileRequest(self.metadata, url,
+                                            CryptoInfo(schema, key, iv))
+        _write_message(self.channel, request)
+        response = _read_message(self.channel)
         return response["content"]["data_id"]
 
     def create_task(self,
-                    function_id,
-                    function_arguments,
-                    executor,
-                    inputs_ownership=[],
-                    outputs_ownership=[]):
+                    function_id: str,
+                    function_arguments: Dict[str, Any],
+                    executor: str,
+                    inputs_ownership: List[OwnerList] = [],
+                    outputs_ownership: List[OwnerList] = []):
         function_arguments = json.dumps(function_arguments)
         request = CreateTaskRequest(self.metadata, function_id,
                                     function_arguments, executor,
                                     inputs_ownership, outputs_ownership)
-        write_message(self.channel, request)
-        response = read_message(self.channel)
+        _write_message(self.channel, request)
+        response = _read_message(self.channel)
         return response["content"]["task_id"]
 
-    def assign_data_to_task(self, task_id, inputs, outputs):
+    def assign_data_to_task(self, task_id: str, inputs: List[DataMap],
+                            outputs: List[DataMap]):
         request = AssignDataRequest(self.metadata, task_id, inputs, outputs)
-        write_message(self.channel, request)
-        response = read_message(self.channel)
+        _write_message(self.channel, request)
+        _ = _read_message(self.channel)
         return
 
-    def approve_task(self, task_id):
+    def approve_task(self, task_id: str):
         request = ApproveTaskRequest(self.metadata, task_id)
-        write_message(self.channel, request)
-        response = read_message(self.channel)
+        _write_message(self.channel, request)
+        _ = _read_message(self.channel)
         return
 
-    def invoke_task(self, task_id):
+    def invoke_task(self, task_id: str):
         request = InvokeTaskRequest(self.metadata, task_id)
-        write_message(self.channel, request)
-        response = read_message(self.channel)
+        _write_message(self.channel, request)
+        response = _read_message(self.channel)
         assert (response["result"] == "ok")
 
-    def get_task_result(self, task_id):
+    def get_task_result(self, task_id: str):
         request = GetTaskRequest(self.metadata, task_id)
 
         while True:
-            write_message(self.channel, request)
-            response = read_message(self.channel)
+            _write_message(self.channel, request)
+            response = _read_message(self.channel)
             time.sleep(1)
             if response["content"]["status"] == 10:
                 break
@@ -265,21 +418,25 @@ class FrontendClient:
         return response["content"]["result"]["result"]["Ok"]["return_value"]
 
 
-def write_message(sock, message):
+def _write_message(sock: ssl.SSLSocket, message: Any):
+    class RequestEncoder(json.JSONEncoder):
+        def default(self, o):
+            return o.__dict__
+
     message = json.dumps(message, cls=RequestEncoder).encode()
     sock.write(struct.pack(">Q", len(message)))
     sock.write(message)
 
 
-def read_message(sock):
+def _read_message(sock: ssl.SSLSocket):
     response_len = struct.unpack(">Q", sock.read(8))
     response = sock.read(response_len[0])
     response = json.loads(response)
     return response
 
 
-def verify_report(as_root_ca_cert_path, enclave_info_path, cert,
-                  endpoint_name):
+def _verify_report(as_root_ca_cert_path: str, enclave_info_path: str,
+                   cert: Dict[str, Any], endpoint_name: str):
     if os.environ.get('SGX_MODE') == 'SW':
         return
 


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