Uploading programs and ciphertexts
Before interacting with an FHE application, the program must be uploaded to SPF and user inputs must be encrypted and stored. This section covers uploading programs, encrypting values, and uploading ciphertexts using the TypeScript client library.
Ensure the client is initialized before using these functions.
Type safety with branded types
The SPF client uses TypeScript branded types to provide compile-time type safety for identifiers and handles. These types are hex strings with a 0x prefix, but TypeScript distinguishes between different kinds of identifiers:
LibraryId- Identifies uploaded FHE programsCiphertextId- Identifies uploaded ciphertextsRunHandle- Identifies program execution runsDecryptHandle- Identifies decryption requests
These branded types work transparently when passing values between functions, but prevent accidentally mixing up different types of identifiers (for example, using a ciphertext ID where a library ID is expected). The types are compatible with regular hex strings, so you can store them as strings and use them directly.
Program upload
To upload a compiled FHE program to SPF, use the uploadProgram() function:
export async function uploadProgramExample(
programPath: string,
): Promise<string> {
// Read the compiled program file
const programBytes = new Uint8Array(readFileSync(programPath));
// Upload to SPF
const libraryId: string = await spf.uploadProgram(programBytes);
console.log("Library ID:", libraryId);
// Example output: 0x7f7e6993da0d371c4f7f4573df315fe3638d253b74c3f98e946f9b9737b5b51b
return libraryId;
}
The uploadProgram() function uploads the compiled program binary to SPF and returns a unique library identifier. This library ID is used when submitting program runs.
Parameters:
programBytes:Uint8Array- The compiled FHE program binary
Returns: Promise<LibraryId> - The library identifier (branded hex string with 0x prefix)
Encrypting values
To encrypt values for use as program inputs, use the encryptValue() function:
export async function encryptValueExample(): Promise<Uint8Array> {
// Encrypt an unsigned 16-bit value
const ciphertext1 = await spf.encryptValue(42, 16);
// Encrypt a signed 8-bit value (negative values are automatically treated as signed)
const ciphertext2 = await spf.encryptValue(-1, 8);
// Encrypt a bigint value
const ciphertext3 = await spf.encryptValue(100n, 16);
return ciphertext1;
}
Parameters:
value:number | bigint- The plaintext value to encryptbitWidth:8 | 16 | 32 | 64- The bit width
Returns: Promise<Uint8Array> - The encrypted ciphertext bytes
Ciphertext upload
To upload ciphertexts to SPF, use the uploadCiphertext() function:
export async function uploadCiphertextExample(
signer: spf.PrivateKeySigner,
): Promise<string> {
// Encrypt a value
const ciphertext = await spf.encryptValue(42, 16);
// Upload the ciphertext
const ciphertextId: string = await spf.uploadCiphertext(signer, ciphertext);
console.log("Ciphertext ID:", ciphertextId);
// Example output: 0xb1f6efd65778acb7a92b49034467ea6abedc9af4ce198ded85ddfd13fe45039d
return ciphertextId;
}
The uploadCiphertext() function uploads encrypted data to SPF and returns a unique ciphertext identifier (a keccak256 hash of the ciphertext bytes). The signer is used for authentication, and the uploader becomes the initial admin of the ciphertext.
Parameters:
signer:AnySigner- Signer for authenticationciphertextBytes:Uint8Array- The encrypted ciphertext bytes
Returns: Promise<CiphertextId> - The ciphertext identifier (branded hex string with 0x prefix)
Complete example
Here is a complete example that encrypts a value, uploads it, and grants access:
export async function completeUploadExample(
signer: spf.PrivateKeySigner,
runnerAddress: spf.Address,
libraryId: spf.LibraryId,
programName: string,
): Promise<spf.CiphertextId> {
// Encrypt a vote
const plaintextValue = -1; // Reject
const ciphertext = await spf.encryptValue(plaintextValue, 8);
// Upload the ciphertext
const ciphertextId = await spf.uploadCiphertext(signer, ciphertext);
// Grant run access to the runner
const aclAppliedId = await spf.allowRun(
signer,
ciphertextId,
runnerAddress,
libraryId,
spf.asProgramName(programName),
);
console.log("Vote uploaded with run access:", aclAppliedId);
return aclAppliedId;
}