The Client provides an interface for users to send requests and process Node data received from the Hub.
The Client communicates with the Node via the gRPC protocol, sending input data and receiving proofs.
Main Process
Establishing HTTPS Connection
Request Node List: Send a request to the Hub to obtain the Node list.
Receive Node Data: Receive the Node list from the Hub.
Request Node List (with Payment): First, establish a new order request with the Hub and obtain the order number. Afterward, call the corresponding contract function for payment. Once the payment is completed, use the order number to request the Node list from the Hub.
Receive Node Data: Receive the Node list from the Hub.
Code Example
Users first establish an HTTPS connection with the Hub, which returns a JSON object containing response codes and node addresses array.
A response code of 0 indicates a successful request.
Define the gRPC service and message formats using .proto files.
syntax ="proto3";packageprove_service;message ProveBaseRequest {string prover_id =1; // Unique identifier for the proverstring circuit_template_id =2; // Circuit template identifierstring input_data =3; // Input data used to generate the proofbool is_encrypted =4; // True if the input data is encryptedstring auth_token =5; // Authentication token}message StatusResponse {int32 code =1; // Status codestring msg =2; // Additional status information}message ProveRequest { ProveBaseRequest base_request =1; // Base request for all proof requests}message ProveWithWitnessRequest { ProveBaseRequest base_request =1; // Base request for all proof requests}message ProveNosha256Request { ProveBaseRequest base_request =1; // Base request for all proof requestsint32 length =2; // Length of the input data}message ProveNosha256WithWitnessRequest { ProveBaseRequest base_request =1; // Base request for all proof requestsint32 length =2; // Length of the input data}message ProveNosha256OffchainRequest { ProveBaseRequest base_request =1; // Base request for all proof requestsint32 length =2; // Length of the input data}message GetPublicKeyResponse { StatusResponse base_response =1; // Status code and messagestring public_key =2; // Retrieved public key string}message ProveResponse { StatusResponse base_response =1; // Status code and messagestring proof_data =2; // Generated proof data}message ProveWithWitnessResponse { StatusResponse base_response =1; // Status code and messagestring proof_data =2; // Generated proof datastring witness_data =3; // Additional witness data related to the proof}message ProveNosha256Response { StatusResponse base_response =1; // Status code and messagestring proof_data =2; // Generated proof data}message ProveNosha256WithWitnessResponse { StatusResponse base_response =1; // Status code and messagestring proof_data =2; // Generated proof datastring witness_data =3; // Additional witness data related to the proof}message ProveNosha256OffchainResponse { StatusResponse base_response =1; // Status code and message bytes proof_data =2; // Generated proof datastring witness_data =3; // Additional witness data related to the proof}message Empty {// An empty message used for requests or responses that don't require additional parameters}service ProveService { rpc Prove(ProveRequest) returns (ProveResponse); // Generates a proof using the provided parameters rpc ProveWithWitness(ProveWithWitnessRequest) returns (ProveWithWitnessResponse); // Generates a proof with witness rpc ProveNosha256(ProveNosha256Request) returns (ProveNosha256Response); // Processes the input without SHA256 and returns a proof
rpc ProveNosha256WithWitness(ProveNosha256WithWitnessRequest) returns (ProveNosha256WithWitnessResponse); // Processes the input without SHA256 and returns a proof and witness
rpc ProveNosha256Offchain(ProveNosha256OffchainRequest) returns (ProveNosha256OffchainResponse); // Processes the input without SHA256 and returns a proof and witness for offchain verify
rpc GetPublicKey(Empty) returns (GetPublicKeyResponse); // Retrieves the public key for encrypting input data rpc Ping(Empty) returns (Empty); // Ping for health check or to keep the connection alive}
Install gRPC Tools
Install grpcio-tools via PIP to generate gRPC code.
pipinstallgrpcio-tools
Generate gRPC Code
Use protoc to generate Python service and message handling code.
Once the installation is complete, navigate to the directory where the .proto file is stored. Open a command-line tool and ensure that the current working directory is the one where the .proto file is located. Execute the following command to generate Python code: python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. Prove.proto
Use decision tree logic to determine which verification results are valid.
Users store successful proofs in the decision tree, which determines available proofs and returns the correct result:
import timefrom typing import List, Optional, UnionclassProof:def__init__(self) ->None: self.proof_list: List[dict]= []defadd(self,proof:str) ->None:""" Adds a proof to the list along with a timestamp. :param proof: The proof string to add. """ self.proof_list.append({"proof": proof, "timestamp": time.time()})defget_proof(self) -> Union[str,bool]:""" Retrieves the most frequent proof within 1 second of the earliest proof timestamp. :return: The most frequent proof if found, otherwise False. """ifnot self.proof_list:returnFalse# Find the earliest timestamp in the proof list earliest_timestamp =min(proof['timestamp'] for proof in self.proof_list)# Define the threshold timestamp (1 second after the earliest one) threshold_timestamp = earliest_timestamp +1# Filter proofs within the valid time range (<= 1 second from the earliest) valid_proofs = [proof['proof']for proof in self.proof_list if proof['timestamp']<= threshold_timestamp]# Count occurrences of each proof proof_counts ={}for proof in valid_proofs: proof_counts[proof]= proof_counts.get(proof, 0)+1# Find the proof with the highest occurrence max_proof =max(proof_counts, key=proof_counts.get, default=None)return max_proof if max_proof isnotNoneelseFalse
Firstly, execute the proof task and collect the results. This step involves calling the r0prove on each node to collect its returned code (status code), proof (proof result), and node (node address). These results are stored in the prove_results list.
Error Handling
Manage potential issues such as communication errors and data validation errors.
1. Process and filter proof results
Iterate through each item in the prove_results list. For each result:
Check if the code is equal to GRPC_STATUS_ERROR, i.e., check for any errors occurred.
If there is an error, log the error and relevant node information using Logging.error.
If there are no errors, add the proof to the decision tree's proof_list.
2. Retrieve valid proof results from the decision tree
Call the proof_list.get_proof() method to retrieve valid proof results from the decision tree. This method checks all received proofs and selects the most suitable proof based on timestamp and frequency.
3. Handle the final result
If the get_proof() method returns False, indicating no valid proof results, log this status using Logging.error.
If there are valid proof results, log the success information and proof results using Logging.info.
Example code explanation
This code is used to process and validate the results returned by multiple nodes during the proof process. The specific purpose of the code is as follows: