diff --git a/docs/examples/05_download_and_save_keys_to_disc.md b/docs/examples/05_download_and_save_keys_to_disc.md new file mode 100644 index 000000000..a8690b2b4 --- /dev/null +++ b/docs/examples/05_download_and_save_keys_to_disc.md @@ -0,0 +1,49 @@ +This example will demonstrate how to save proving and verifying keys locally for the "transfer_public" in credits.aleo and for any arbitrary Aleo program. + +```typescript +import { + AleoKeyProvider, + CREDITS_PROGRAM_KEYS, + ProvingKey, // these are WASM-backed types + VerifyingKey, +} from "@provablehq/sdk"; +import fs from "node:fs/promises"; +import path from "node:path"; + +const keyProvider = new AleoKeyProvider(); + +// Fetch the on-chain "fee" and "transfer_public" proving and verifying keys +const [feePk, feeVk] = await keyProvider.fetchCreditsKeys(CREDITS_PROGRAM_KEYS.fee_public); +const [txPk, txVk] = await keyProvider.fetchCreditsKeys(CREDITS_PROGRAM_KEYS.transfer_public); + +// For methods that consume or mint a record, the inclusion circuit will be required. +const [incPk, incVk] = await keyProvider.fetchCreditsKeys(CREDITS_PROGRAM_KEYS.inclusion); + +// For a transition method in any deployed Aleo program, use the following pattern to fetch the proving and verifying +// keys associated with that transition. +const keySearchParams = { "cacheKey": "myProgram:myFunction" }; +const [transition_Pk, transition_Vk] = await keyProvider.functionKeys(keySearchParams); + +// You can use this method for saving the keys to disc. +async function writeKeyToFile(key, filePath) { + // Serialize the key into a Uint8Array + const raw = key.toBytes(); // or key.to_bytes() depending on your SDK version + // Then write it as binary + await fs.writeFile(filePath, Buffer.from(raw)); + console.log(`Wrote ${filePath}`); +} + +const keyDir = "./keys"; +await fs.mkdir(keyDir, { recursive: true }); + +await writeKeyToFile(feePk, path.join(keyDir, "fee_public.prover")); +await writeKeyToFile(feeVk, path.join(keyDir, "fee_public.verifier")); +await writeKeyToFile(txPk, path.join(keyDir, "transfer_public.prover")); +await writeKeyToFile(txVk, path.join(keyDir, "transfer_public.verifier")); +await writeKeyToFile(incPk, path.join(keyDir, "inclusion.prover")); +await writeKeyToFile(incVk, path.join(keyDir, "inclusion.verifier")); + +await writeKeyToFile(transition_Pk, path.join(keyDir, "transition.prover")); +await writeKeyToFile(transition_Vk, path.join(keyDir, "transition.verifier")); + + diff --git a/docs/examples/06_transfer_public_using_stored_keys.md b/docs/examples/06_transfer_public_using_stored_keys.md new file mode 100644 index 000000000..f0d45c818 --- /dev/null +++ b/docs/examples/06_transfer_public_using_stored_keys.md @@ -0,0 +1,54 @@ +This example demonstrates how to execute public_transfer using locally saved proving and verifying keys. +```typescript +import { Account, ProgramManager, ProvingKey, VerifyingKey, initThreadPool, OfflineKeyProvider} from '@provablehq/sdk'; +import fs from "node:fs/promises"; + +// Helper method to load the keys from storage. +async function loadFunctionKeyPair(proverPath) { + const proverBytes = await fs.readFile(proverPath); + + const provingKey = ProvingKey.fromBytes(new Uint8Array(proverBytes)); + + return provingKey; +} + +// Initialize multi-threading to allow WASM execution. +await initThreadPoool(); + +// Load the proving and verifying keys for public_transfer and fee_public from local storage. +const feeProvingKey = await loadFunctionKeyPair("./keys/fee_public.prover"); +const transferPublicProvingKey = await loadFunctionKeyPair("./keys/transfer_public.prover"); + +// Create an offline Key provider +const keyProvider = new OfflineKeyProvider(); + + +// Store the proving keys in the offline key provider. +offlineKeyProvider.insertTransferPublicKeys(transferPublicProvingKey); +offlineKeyProvider.insertFeePublicKeys(feeProvingKey); + +// Create program manager using the OfflineKeyProvider and NetworkProvider. +const programManager = new ProgramManager("https://api.explorer.provable.com/v1", offlineKeyProvider); + +// Create or import an account. +const account = new Account(); + +// Set the account as the program caller. +programManager.setAccount(account); + +// Create recipient account. +const recipient = new Account(); + +// Build a transfer_public transaction. +// Publicly send 5 microcredits to the recipient +const transaction = await programManager + .buildTransferPublicTransaction( + 5, // The amount to be transferred in credits (not microcredits) + recipient // The address of the recipient. + .address() + .to_string(), + 0.0 // The optional priority fee amount. + ); + +// Broadcast the transaction to the Aleo network. +const result = await programManager.networkClient.submitTransaction(transaction); \ No newline at end of file diff --git a/docs/examples/07_transfer_private_using_stored_keys.md b/docs/examples/07_transfer_private_using_stored_keys.md new file mode 100644 index 000000000..62126db0e --- /dev/null +++ b/docs/examples/07_transfer_private_using_stored_keys.md @@ -0,0 +1,71 @@ +This example demonstrates how to execute transfer_private using locally saved proving and verifying keys. +```typescript +import { Account, ProgramManager, ProvingKey, VerifyingKey, initThreadPool, OfflineKeyProvider} from '@provable.sdk'; + +// Helper method to load the keys from storage. +async function loadFunctionKeyPair(proverPath, verifierPath) { + const proverBytes = await fs.readFile(proverPath); + const verifierBytes = await fs.readFile(verifierPath); + + const provingKey = ProvingKey.fromBytes(new Uint8Array(proverBytes)); + const verifyingKey = VerifyingKey.fromBytes(new Uint8Array(verifierBytes)); + + return [provingKey, verifyingKey]; +} + +// Download the inclusion proving and verifying keys. +const [inclusionProver, inclusionVerifier] = await loadFunctionKeyPair( + "./keys/inclusion.prover", + "./keys/inclusion.verifier" +); + +// Download the transfer_private proving and verifying keys. +const [transferPrivateProvingKey, transferPrivateVerifyingKey] = await loadFunctionKeyPair( + "./keys/transfer_private.prover", + "./keys/transfer_private.verifier" +); + +// Download the fee_private proving and verifying keys. +const [feeProvingKey, feeVerifyingKey] = await loadFunctionKeyPair( + "./keys/fee_private.prover", + "./keys/fee_private.verifier" +); + +// Initialize multi-threading to allow WASM execution. +await initThreadPoool(); + +// Create a new Account, Program Manager, NetworkClient, KeyProvider, and RecordProvider. +const account = new Account(); +const programManager = new ProgramManager(); +const networkClient = new AleoNetworkClient("https://api.explorer.provable.com/v1"); +const offlineKeyProvider = new OfflineKeyProvider(); +const recordProvider = new NetworkRecordProvider(account, networkClient); + +// Add the keys for fee_private, transfer_private, and the inclusion circuit to the key provider. +offlineKeyProvider.insertFeePrivateKeys(feeProvingKey) +offlineKeyProvider.insertTransferPrivateKeys(transferPrivateProvingKey) +offlineKeyProvider.insertInclusionKeys(inclusionProver); + +// Create an offline query using the latest state root for the inclusion proof. +const offlineQuery = new OfflineQuery("latestStateRoot"); + +// Create the program manager +const programManager = new ProgramManager("https://api.explorer.provable.com/v1", offlineKeyProvider, recordProvider); +programManager.setAccount(account); + +// Build the execution. +const offlineExecuteTx = await programManager.buildExecutionTransaction( + programName: "credits.aleo", + functionName: "transfer_private", + priorityFee: 0.0, + privateFee: true, + inputs: 5u32, + offlineQuery + ); + +// Broadcast the transaction to the network + const txId = await networkClient.broadcastTransaction(offlineExecuteTx); + + + + diff --git a/docs/examples/08_execute_program_with_records.md b/docs/examples/08_execute_program_with_records.md new file mode 100644 index 000000000..043118e14 --- /dev/null +++ b/docs/examples/08_execute_program_with_records.md @@ -0,0 +1,72 @@ +The following template demonstrates how to create an execution using saved proving keys for transactions that either mint or consume records. + +```typescript +import { Account, ProgramManager, ProvingKey, VerifyingKey, initThreadPool, OfflineKeyProvider} from '@provable.sdk'; + +// Helper method to load the keys from storage. +async function loadFunctionKeyPair(proverPath, verifierPath) { + const proverBytes = await fs.readFile(proverPath); + const verifierBytes = await fs.readFile(verifierPath); + + const provingKey = ProvingKey.fromBytes(new Uint8Array(proverBytes)); + const verifyingKey = VerifyingKey.fromBytes(new Uint8Array(verifierBytes)); + + return [provingKey, verifyingKey]; +} + +// Load the inclusion proving and verifying keys. +const [inclusionProver, inclusionVerifier] = await loadFunctionKeyPair( + "./keys/inclusion.prover", + "./keys/inclusion.verifier" +); + +// Load the fee public proving and verifying keys. +const [feeProvingKey, feeVerifyingKey] = await loadFunctionKeyPair( + "./keys/fee_public.prover", + "./keys/fee_public.verifier" +); + +// Load the proving and verifying keys associate with the transition method. +const [transitionProvingKey, transitionVerifyingKey] = await loadFunctionKeyPair( + "./keys/transition.prover", + "./keys/transition.verifier" +); + +// Create a new Account, Program Manager, NetworkClient, KeyProvider, and RecordProvider. +const account = new Account(); +const programManager = new ProgramManager(); +const networkClient = new AleoNetworkClient("https://api.explorer.provable.com/v1"); +const offlineKeyProvider = new OfflineKeyProvider(); +const recordProvider = new NetworkRecordProvider(account, networkClient); + +// Add the keys for fee_public and the inclusion circuit to the key provider. +offlineKeyProvider.insertFeePublicKeys(feeProvingKey) +offlineKeyProvider.insertInclusionKeys(inclusionProver); + +// Cache the proving key for the transition method. +// Replace "program_name" and "transition_name" with the your program and transition method. +OfflineKeyProvider.cacheKeys("program_name.aleo/transition_name", transitionProvingKey, transitionerifyingKey); + +// Create an offline search params object. +const offlineSearchParams = new OfflineSearchParams("program_name.aleo/transition_name"); + +// Create an offline query using the latest state root for the inclusion proof. +const offlineQuery = new OfflineQuery("latestStateRoot"); + +// Create the program manager +const programManager = new ProgramManager("https://api.explorer.provable.com/v1", offlineKeyProvider, recordProvider); +programManager.setAccount(account); + +// Build the execution. +const offlineExecuteTx = await programManager.buildExecutionTransaction( + programName: "program_name.aleo", + functionName: "transition_method", + priorityFee: 0.0, + privateFee: false, + inputs: 5u32, // replace with whatever input(s) your transition method requires + offlineSearchParams, + offlineQuery + ); + +// Broadcast the transaction to the network + const txId = await networkClient.broadcastTransaction(offlineExecuteTx); \ No newline at end of file