V2
Confidential Prover Implementation
In Version 2, the market maker only needs to instruct Kalypso on how to generate proofs based on a given set of inputs—both public and private. This is achieved by implementing two main traits:
Both traits work within a secure enclave where sensitive operations (like decryption) occur.
Implementing GeneratorTrait
The GeneratorTrait
is used to generate cryptographic proofs. Below is an example implementation using a dummy struct called NullConfProver
:
#[derive(Default)]
struct NullConfProver;
#[async_trait]
impl GeneratorTrait for NullConfProver {
async fn generate_proof(&self, _input: InputPayload) -> GenerateProofResponse {
// Retrieve the public input from the provided payload.
let public_input = _input.get_public();
// Retrieve the ECIES private key from a secure location inside the enclave.
// The key is first attempted to be read from '/app/secp.sec'. If not found,
// it falls back to reading from './app/secp.sec'.
let ecies_private_key = match fs::read("/app/secp.sec").await {
Ok(key) => key,
Err(_) => fs::read("./app/secp.sec").await?,
};
// Decrypt the encrypted secrets using the ECIES private key.
// This returns the plain (unencrypted) secrets.
let secret = _input.get_plain_secrets_from_encrypted_secrets(ecies_private_key)
.unwrap();
// You can now use both the public input and the decrypted secret
// to generate the cryptographic proof.
// Insert your actual proof generation logic here.
unimplemented!()
}
async fn benchmark(&self) -> BenchmarkResponse {
// Implement your benchmarking logic here.
unimplemented!()
}
}
How It Works
-
Extracting Public Input:
The methodgenerate_proof
starts by extracting the public part of the input using_input.get_public()
. -
Accessing the Private Key:
It securely reads the ECIES private key from the enclave. The key is crucial for decrypting any encrypted secrets provided in the input. -
Decrypting Secrets:
The function then calls_input.get_plain_secrets_from_encrypted_secrets
with the private key to retrieve the unencrypted secrets. -
Proof Generation:
Once both the public and secret inputs are available, your custom logic to generate the cryptographic proof should replace theunimplemented!()
placeholder.
Implementing IVSTrait
The IVSTrait
is designed to validate inputs and verify proofs. Below is an example implementation for NullConfProver
:
#[async_trait]
impl IVSTrait for NullConfProver {
async fn check_inputs(&self, _input: InputPayload) -> CheckInputResponse {
// Retrieve the public input.
let public_input = _input.get_public();
// Access the ECIES private key securely inside the enclave.
let ecies_private_key = match fs::read("/app/secp.sec").await {
Ok(key) => key,
Err(_) => fs::read("./app/secp.sec").await?,
};
// Decrypt and retrieve the plain secrets from the encrypted ones.
let secret = _input.get_plain_secrets_from_encrypted_secrets(ecies_private_key)
.unwrap();
// Insert your logic to check and validate the inputs.
unimplemented!()
}
async fn check_inputs_and_proof(
&self,
_input: VerifyInputsAndProof,
) -> VerifyInputAndProofResponse {
// Extract the individual components from the input.
let public_input = _input.public_input;
let private_input = _input.private_input;
let proof = _input.proof;
// Insert your logic to verify that the inputs match the proof.
unimplemented!()
}
}
How It Works
-
Input Validation:
Thecheck_inputs
method retrieves the public input and uses the private key to decrypt any encrypted secrets. It is here that you should implement any input validation logic. -
Combined Verification:
Thecheck_inputs_and_proof
method accepts a payload that bundles the public input, private input, and the cryptographic proof. This is where you implement the logic to verify that the provided inputs are consistent with the proof.
By implementing the GeneratorTrait
and IVSTrait
, you enable the Confidential Prover to:
- Generate cryptographic proofs using both public and secret inputs.
- Validate input data and verify proofs within a secure enclave environment.
Replace the unimplemented!()
placeholders with your actual logic to meet your application's requirements.
Final Step Building Image
-
Clone the repo and switch to the prover template directory.
git clone https://github.com/marlinprotocol/kalypso-enclave-setups
cd kalypso-enclave-setups/base-prover-setupbase-prover-setup contains the following files:
├── build.sh
├── Dockerfile
├── generator-client
├── refreshEnclave.sh
├── setup.sh
└── supervisord.conf -
Copy the confidential-prover created in the previous sub-section to the current repo.
cp ../path_to/confidential-prover .
-
Add the confidential-prover to Dockerfile.
./kalypso-enclave-setups/base-prover-setup/Dockerfile# ... existing commands
# your executables comes after this
COPY confidential-prover .
# Don't change the entry point
ENTRYPOINT [ "/app/setup.sh" ] -
Finally, build the image. You must have nitro-cli installed, as is explained in the section on building and running enclaves.
./build.sh
This command will build the enclave and print the PCRs of the image. Note down the PCRs of image. They will be used later.
-
Make sure you backup the enclave image file.
cp nitro-enclave.eif ./path/to/backup_location
It is recommended to host nitro-enclave.eif
on a service like IPFS or S3 so that the image is available for Generators to participate in the Market