Compute
Blind computation requires three elements:
- Storing of a Program (via self or by someone else)
- Invoking the program with your parameters
- Retrieving the computed results
Note: in order to use these functions, you (as the developer) should have created Nada programs to interact with. See this guide if you have not done this process.
useNilStoreProgram
To store a program, you would have computed a XXX.nada.bin
file after you built a successful nada program. You will need to upload this file via the FileReader to upload the program. The mutation.execute({ name, program })
part should automatically take in your program + name.
"use client";
import { useNilStoreProgram } from "@nillion/client-react-hooks";
import { type FC, useRef, useState } from "react";
export const StoreProgram: FC = () => {
const mutation = useNilStoreProgram();
const [name, setName] = useState("");
const [program, setProgram] = useState<Uint8Array | null>(null);
const programDefined = name && program;
const fileInputRef = useRef<HTMLInputElement>(null);
let id = "";
if (mutation.isSuccess) {
id = mutation.data;
} else if (mutation.isError) {
id = mutation.error.message;
}
function handleFileChange(event: React.ChangeEvent<HTMLInputElement>): void {
const file = event.target.files?.[0];
if (file) {
setName(file.name);
const reader = new FileReader();
reader.onload = (e) => {
const content = e.target?.result;
if (content) {
setProgram(new Uint8Array(content as ArrayBuffer));
}
};
reader.readAsArrayBuffer(file);
}
}
function handleClick(): void {
if (!program) throw new Error("Expected `program` to be undefined");
mutation.execute({ name, program });
}
return (
<div>
<h2>Store Program</h2>
<ol>
<li>Status: {mutation.status}</li>
<li>Name: {name}</li>
<li>
Program:{" "}
<input type="file" ref={fileInputRef} onChange={handleFileChange} />
</li>
<li>Program Id: {id}</li>
</ol>
<button type="button" disabled={!programDefined} onClick={handleClick}>
Execute
</button>
</div>
);
};
useNilInvokeCompute
To invoke a program, you pass in the programId
of the program you have uploaded with considerations of the inputs you want to provide in your options
. computeTimeValues
with respect to name
and value
are what you want to adjust.
const options = {
programId,
inputBindings: [{ party: "Party1", user: client.id }],
outputBindings: [{ party: "Party1", users: [client.id] }],
valueIds: [],
computeTimeValues: [
{
name: "A",
value: NadaValue.new_secret_integer("10"),
},
{
name: "B",
value: NadaValue.new_secret_integer("4"),
},
],
};
"use client";
import {
useNilInvokeCompute,
useNilOverwritePermissions,
useNillion,
} from "@nillion/client-react-hooks";
import { NadaValue, ProgramId, Uuid } from "@nillion/client-vms";
import { type ChangeEvent, type FC, useState } from "react";
export const InvokeCompute: FC = () => {
const { client } = useNillion();
const mutation = useNilInvokeCompute();
const [programId, setProgramId] = useState("");
const isValidProgramId = ProgramId.safeParse(programId).success;
function handleChange(event: ChangeEvent<HTMLInputElement>): void {
setProgramId(event.target.value);
}
function handleClick(): void {
// Assumes addition_division.py
const options = {
programId,
inputBindings: [{ party: "Party1", user: client.id }],
outputBindings: [{ party: "Party1", users: [client.id] }],
valueIds: [],
computeTimeValues: [
{
name: "A",
value: NadaValue.new_secret_integer("10"),
},
{
name: "B",
value: NadaValue.new_secret_integer("4"),
},
],
};
mutation.execute(options);
}
let resultId = "";
if (mutation.isSuccess) {
resultId = mutation.data;
} else if (mutation.isError) {
resultId = mutation.error.message;
}
return (
<div>
<h2>Invoke Compute</h2>
<ol>
<li>Status: {mutation.status}</li>
<li>
Program id:{" "}
<input type="text" value={programId} onChange={handleChange} />
</li>
<li>Compute result id: {resultId}</li>
</ol>
<button type="button" disabled={!isValidProgramId} onClick={handleClick}>
Execute
</button>
</div>
);
};
useNilRetrieveComputeResults
To retrieve, you simply pass in the id
from the previous invocation.
"use client";
import {
useNilInvokeCompute,
useNilOverwritePermissions,
useNilRetrieveComputeResults,
} from "@nillion/client-react-hooks";
import { Uuid } from "@nillion/client-vms";
import { type ChangeEvent, type FC, useState } from "react";
export const RetrieveComputeResults: FC = () => {
const mutation = useNilRetrieveComputeResults();
const [id, setId] = useState("");
const isValidUuid = Uuid.safeParse(id).success;
let data = "";
if (mutation.isSuccess) {
// stringify cannot handle BigInts
data = data = JSON.stringify(mutation.data, (_, v) =>
typeof v === "bigint" ? v.toString() : v,
);
} else if (mutation.isError) {
data = mutation.error.message;
}
function handleChange(event: ChangeEvent<HTMLInputElement>): void {
setId(event.target.value);
}
function handleClick(): void {
const options = { id };
mutation.execute(options);
}
return (
<div>
<h2>Retrieve Compute Results</h2>
<ol>
<li>Status: {mutation.status}</li>
<li>
Result Id: <input type="text" value={id} onChange={handleChange} />
</li>
<li>Results: {data}</li>
</ol>
<button type="button" disabled={!isValidUuid} onClick={handleClick}>
Execute
</button>
</div>
);
};