Skip to content

Commit 5dc5587

Browse files
Merge pull request #907 from ProvableHQ/feat/key-provider-fix-example
[Fix] Ensure credits.aleo keys are fetched from SnarkVM instead of a remote
2 parents 6b53891 + 67ad3f1 commit 5dc5587

File tree

13 files changed

+774
-529
lines changed

13 files changed

+774
-529
lines changed

sdk/src/function-key-provider.ts

Lines changed: 78 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
VerifyingKey,
44
CREDITS_PROGRAM_KEYS,
55
KEY_STORE,
6+
Key,
67
PRIVATE_TRANSFER,
78
PRIVATE_TO_PUBLIC_TRANSFER,
89
PUBLIC_TRANSFER,
@@ -32,6 +33,7 @@ interface KeySearchParams {
3233
* verifierUri to fetch keys via HTTP from a remote resource as well as a unique cacheKey to store the keys in memory.
3334
*/
3435
class AleoKeyProviderParams implements KeySearchParams {
36+
name: string | undefined;
3537
proverUri: string | undefined;
3638
verifierUri: string | undefined;
3739
cacheKey: string | undefined;
@@ -44,10 +46,11 @@ class AleoKeyProviderParams implements KeySearchParams {
4446
*
4547
* @param { AleoKeyProviderInitParams } params - Optional search parameters
4648
*/
47-
constructor(params: {proverUri?: string, verifierUri?: string, cacheKey?: string}) {
49+
constructor(params: {proverUri?: string, verifierUri?: string, cacheKey?: string, name?: string}) {
4850
this.proverUri = params.proverUri;
4951
this.verifierUri = params.verifierUri;
5052
this.cacheKey = params.cacheKey;
53+
this.name = params.name;
5154
}
5255
}
5356

@@ -328,6 +331,13 @@ class AleoKeyProvider implements FunctionKeyProvider {
328331
let proverUrl;
329332
let verifierUrl;
330333
let cacheKey;
334+
if ("name" in params && typeof params["name"] == "string") {
335+
let key = CREDITS_PROGRAM_KEYS.getKey(params["name"]);
336+
if (!(key instanceof Error)) {
337+
return this.fetchCreditsKeys(key);
338+
}
339+
}
340+
331341
if ("proverUri" in params && typeof params["proverUri"] == "string") {
332342
proverUrl = params["proverUri"];
333343
}
@@ -341,7 +351,7 @@ class AleoKeyProvider implements FunctionKeyProvider {
341351
}
342352

343353
if (proverUrl && verifierUrl) {
344-
return await this.fetchKeys(proverUrl, verifierUrl, cacheKey);
354+
return await this.fetchRemoteKeys(proverUrl, verifierUrl, cacheKey);
345355
}
346356

347357
if (cacheKey) {
@@ -376,7 +386,7 @@ class AleoKeyProvider implements FunctionKeyProvider {
376386
* CREDITS_PROGRAM_KEYS.transfer_private.verifier,
377387
* );
378388
*/
379-
async fetchKeys(proverUrl: string, verifierUrl: string, cacheKey?: string): Promise<FunctionKeyPair | Error> {
389+
async fetchRemoteKeys(proverUrl: string, verifierUrl: string, cacheKey?: string): Promise<FunctionKeyPair | Error> {
380390
try {
381391
// If cache is enabled, check if the keys have already been fetched and return them if they have
382392
if (this.cacheOption) {
@@ -406,16 +416,67 @@ class AleoKeyProvider implements FunctionKeyProvider {
406416
}
407417
}
408418

409-
bondPublicKeys(): Promise<FunctionKeyPair | Error> {
410-
return this.fetchKeys(CREDITS_PROGRAM_KEYS.bond_public.prover, CREDITS_PROGRAM_KEYS.bond_public.verifier, CREDITS_PROGRAM_KEYS.bond_public.locator)
419+
/***
420+
* Fetches the proving key from a remote source.
421+
*
422+
* @param proverUrl
423+
* @param cacheKey
424+
*
425+
* @returns {Promise<ProvingKey | Error>} Proving key for the specified program
426+
*/
427+
async fetchProvingKey(proverUrl: string, cacheKey?: string): Promise<ProvingKey | Error> {
428+
try {
429+
// If cache is enabled, check if the keys have already been fetched and return them if they have
430+
if (this.cacheOption) {
431+
if (!cacheKey) {
432+
cacheKey = proverUrl;
433+
}
434+
const value = this.cache.get(cacheKey);
435+
if (typeof value !== "undefined") {
436+
return ProvingKey.fromBytes(value[0]);
437+
} else {
438+
console.debug("Fetching proving keys from url " + proverUrl);
439+
const provingKey = <ProvingKey>ProvingKey.fromBytes(await this.fetchBytes(proverUrl));
440+
return provingKey;
441+
}
442+
}
443+
else {
444+
const provingKey = <ProvingKey>ProvingKey.fromBytes(await this.fetchBytes(proverUrl));
445+
return provingKey;
446+
}
447+
} catch (error) {
448+
throw new Error(`Error: ${error} fetching fee proving keys from ${proverUrl}`);
449+
}
450+
}
451+
452+
async fetchCreditsKeys(key: Key): Promise<FunctionKeyPair | Error> {
453+
try {
454+
if (!this.cache.has(key.locator) || !this.cacheOption) {
455+
const verifying_key = key.verifyingKey()
456+
const proving_key = <ProvingKey>await this.fetchProvingKey(key.prover, key.locator);
457+
if (this.cacheOption) {
458+
this.cache.set(CREDITS_PROGRAM_KEYS.bond_public.locator, [proving_key.toBytes(), verifying_key.toBytes()]);
459+
}
460+
return [proving_key, verifying_key];
461+
} else {
462+
const keyPair = <CachedKeyPair>this.cache.get(key.locator);
463+
return [ProvingKey.fromBytes(keyPair[0]), VerifyingKey.fromBytes(keyPair[1])];
464+
}
465+
} catch (error) {
466+
throw new Error(`Error: fetching credits.aleo keys: ${error}`);
467+
}
468+
}
469+
470+
async bondPublicKeys(): Promise<FunctionKeyPair | Error> {
471+
return this.fetchCreditsKeys(CREDITS_PROGRAM_KEYS.bond_public);
411472
}
412473

413474
bondValidatorKeys(): Promise<FunctionKeyPair | Error> {
414-
return this.fetchKeys(CREDITS_PROGRAM_KEYS.bond_validator.prover, CREDITS_PROGRAM_KEYS.bond_validator.verifier, CREDITS_PROGRAM_KEYS.bond_validator.locator)
475+
return this.fetchCreditsKeys(CREDITS_PROGRAM_KEYS.bond_validator);
415476
}
416477

417478
claimUnbondPublicKeys(): Promise<FunctionKeyPair | Error> {
418-
return this.fetchKeys(CREDITS_PROGRAM_KEYS.claim_unbond_public.prover, CREDITS_PROGRAM_KEYS.claim_unbond_public.verifier, CREDITS_PROGRAM_KEYS.claim_unbond_public.locator)
479+
return this.fetchCreditsKeys(CREDITS_PROGRAM_KEYS.claim_unbond_public)
419480
}
420481

421482
/**
@@ -438,15 +499,15 @@ class AleoKeyProvider implements FunctionKeyProvider {
438499
*/
439500
async transferKeys(visibility: string): Promise<FunctionKeyPair | Error> {
440501
if (PRIVATE_TRANSFER.has(visibility)) {
441-
return await this.fetchKeys(CREDITS_PROGRAM_KEYS.transfer_private.prover, CREDITS_PROGRAM_KEYS.transfer_private.verifier, CREDITS_PROGRAM_KEYS.transfer_private.locator);
502+
return await this.fetchCreditsKeys(CREDITS_PROGRAM_KEYS.transfer_private);
442503
} else if (PRIVATE_TO_PUBLIC_TRANSFER.has(visibility)) {
443-
return await this.fetchKeys(CREDITS_PROGRAM_KEYS.transfer_private_to_public.prover, CREDITS_PROGRAM_KEYS.transfer_private_to_public.verifier, CREDITS_PROGRAM_KEYS.transfer_private_to_public.locator);
504+
return await this.fetchCreditsKeys(CREDITS_PROGRAM_KEYS.transfer_private_to_public);
444505
} else if (PUBLIC_TRANSFER.has(visibility)) {
445-
return await this.fetchKeys(CREDITS_PROGRAM_KEYS.transfer_public.prover, CREDITS_PROGRAM_KEYS.transfer_public.verifier, CREDITS_PROGRAM_KEYS.transfer_public.locator);
506+
return await this.fetchCreditsKeys(CREDITS_PROGRAM_KEYS.transfer_public);
446507
} else if (PUBLIC_TRANSFER_AS_SIGNER.has(visibility)) {
447-
return await this.fetchKeys(CREDITS_PROGRAM_KEYS.transfer_public_as_signer.prover, CREDITS_PROGRAM_KEYS.transfer_public_as_signer.verifier, CREDITS_PROGRAM_KEYS.transfer_public_as_signer.locator);
508+
return await this.fetchCreditsKeys(CREDITS_PROGRAM_KEYS.transfer_public_as_signer);
448509
} else if (PUBLIC_TO_PRIVATE_TRANSFER.has(visibility)) {
449-
return await this.fetchKeys(CREDITS_PROGRAM_KEYS.transfer_public_to_private.prover, CREDITS_PROGRAM_KEYS.transfer_public_to_private.verifier, CREDITS_PROGRAM_KEYS.transfer_public_to_private.locator);
510+
return await this.fetchCreditsKeys(CREDITS_PROGRAM_KEYS.transfer_public_to_private);
450511
} else {
451512
throw new Error("Invalid visibility type");
452513
}
@@ -458,7 +519,7 @@ class AleoKeyProvider implements FunctionKeyProvider {
458519
* @returns {Promise<FunctionKeyPair | Error>} Proving and verifying keys for the join function
459520
*/
460521
async joinKeys(): Promise<FunctionKeyPair | Error> {
461-
return await this.fetchKeys(CREDITS_PROGRAM_KEYS.join.prover, CREDITS_PROGRAM_KEYS.join.verifier, CREDITS_PROGRAM_KEYS.join.locator);
522+
return await this.fetchCreditsKeys(CREDITS_PROGRAM_KEYS.join);
462523
}
463524

464525
/**
@@ -467,7 +528,7 @@ class AleoKeyProvider implements FunctionKeyProvider {
467528
* @returns {Promise<FunctionKeyPair | Error>} Proving and verifying keys for the split function
468529
* */
469530
async splitKeys(): Promise<FunctionKeyPair | Error> {
470-
return await this.fetchKeys(CREDITS_PROGRAM_KEYS.split.prover, CREDITS_PROGRAM_KEYS.split.verifier, CREDITS_PROGRAM_KEYS.split.locator);
531+
return await this.fetchCreditsKeys(CREDITS_PROGRAM_KEYS.split);
471532
}
472533

473534
/**
@@ -476,7 +537,7 @@ class AleoKeyProvider implements FunctionKeyProvider {
476537
* @returns {Promise<FunctionKeyPair | Error>} Proving and verifying keys for the fee function
477538
*/
478539
async feePrivateKeys(): Promise<FunctionKeyPair | Error> {
479-
return await this.fetchKeys(CREDITS_PROGRAM_KEYS.fee_private.prover, CREDITS_PROGRAM_KEYS.fee_private.verifier, CREDITS_PROGRAM_KEYS.fee_private.locator);
540+
return await this.fetchCreditsKeys(CREDITS_PROGRAM_KEYS.fee_private);
480541
}
481542

482543
/**
@@ -485,7 +546,7 @@ class AleoKeyProvider implements FunctionKeyProvider {
485546
* @returns {Promise<FunctionKeyPair | Error>} Proving and verifying keys for the fee function
486547
*/
487548
async feePublicKeys(): Promise<FunctionKeyPair | Error> {
488-
return await this.fetchKeys(CREDITS_PROGRAM_KEYS.fee_public.prover, CREDITS_PROGRAM_KEYS.fee_public.verifier, CREDITS_PROGRAM_KEYS.fee_public.locator);
549+
return await this.fetchCreditsKeys(CREDITS_PROGRAM_KEYS.fee_public);
489550
}
490551

491552
/**
@@ -544,7 +605,7 @@ class AleoKeyProvider implements FunctionKeyProvider {
544605
}
545606

546607
unBondPublicKeys(): Promise<FunctionKeyPair | Error> {
547-
return this.fetchKeys(CREDITS_PROGRAM_KEYS.unbond_public.prover, CREDITS_PROGRAM_KEYS.unbond_public.verifier, CREDITS_PROGRAM_KEYS.unbond_public.locator);
608+
return this.fetchCreditsKeys(CREDITS_PROGRAM_KEYS.unbond_public);
548609
}
549610
}
550611

sdk/src/index.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {VerifyingKey, Metadata} from "@provablehq/wasm";
33
const KEY_STORE = Metadata.baseUrl();
44

55
interface Key {
6+
name: string,
67
locator: string,
78
prover: string,
89
verifier: string,
@@ -18,6 +19,7 @@ function convert(metadata: Metadata): Key {
1819
}
1920

2021
return {
22+
name: metadata.name,
2123
locator: metadata.locator,
2224
prover: metadata.prover,
2325
verifier: metadata.verifier,
@@ -41,6 +43,13 @@ const CREDITS_PROGRAM_KEYS = {
4143
transfer_public_as_signer: convert(Metadata.transfer_public_as_signer()),
4244
transfer_public_to_private: convert(Metadata.transfer_public_to_private()),
4345
unbond_public: convert(Metadata.unbond_public()),
46+
getKey: function(key: string): Key | Error {
47+
if (this.hasOwnProperty(key)) {
48+
return (this as any)[key] as Key;
49+
} else {
50+
return new Error(`Key "${key}" not found.`);
51+
}
52+
}
4453
};
4554

4655
const PRIVATE_TRANSFER_TYPES = new Set([
@@ -175,6 +184,7 @@ export {
175184
FunctionKeyPair,
176185
FunctionKeyProvider,
177186
Input,
187+
Key,
178188
KeySearchParams,
179189
NetworkRecordProvider,
180190
ProgramImports,

sdk/src/program-manager.ts

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -597,7 +597,6 @@ class ProgramManager {
597597
* @param {string} transferType The type of transfer to perform - options: 'private', 'privateToPublic', 'public', 'publicToPrivate'
598598
* @param {number} fee The fee to pay for the transfer
599599
* @param {boolean} privateFee Use a private record to pay the fee. If false this will use the account's public credit balance
600-
* @param {string | undefined} caller The caller of the function (if calling transfer_public)
601600
* @param {RecordSearchParams | undefined} recordSearchParams Optional parameters for finding the amount and fee
602601
* records for the transfer transaction
603602
* @param {RecordPlaintext | string} amountRecord Optional amount record to use for the transfer
@@ -625,7 +624,6 @@ class ProgramManager {
625624
transferType: string,
626625
fee: number,
627626
privateFee: boolean,
628-
caller?: string,
629627
recordSearchParams?: RecordSearchParams,
630628
amountRecord?: RecordPlaintext | string,
631629
feeRecord?: RecordPlaintext | string,
@@ -674,14 +672,13 @@ class ProgramManager {
674672
}
675673

676674
// Build an execution transaction and submit it to the network
677-
return await WasmProgramManager.buildTransferTransaction(executionPrivateKey, amount, recipient, transferType, caller, amountRecord, fee, feeRecord, this.host, transferProvingKey, transferVerifyingKey, feeProvingKey, feeVerifyingKey, offlineQuery);
675+
return await WasmProgramManager.buildTransferTransaction(executionPrivateKey, amount, recipient, transferType, amountRecord, fee, feeRecord, this.host, transferProvingKey, transferVerifyingKey, feeProvingKey, feeVerifyingKey, offlineQuery);
678676
}
679677

680678
/**
681679
* Build a transfer_public transaction to transfer credits to another account for later submission to the Aleo network
682680
*
683681
* @param {number} amount The amount of credits to transfer
684-
* @param {string} caller The caller of the transfer (may be different from the signer)
685682
* @param {string} recipient The recipient of the transfer
686683
* @param {string} transferType The type of transfer to perform - options: 'private', 'privateToPublic', 'public', 'publicToPrivate'
687684
* @param {number} fee The fee to pay for the transfer
@@ -696,13 +693,12 @@ class ProgramManager {
696693
*/
697694
async buildTransferPublicTransaction(
698695
amount: number,
699-
caller: string,
700696
recipient: string,
701697
fee: number,
702698
privateKey?: PrivateKey,
703699
offlineQuery?: OfflineQuery
704700
): Promise<Transaction | Error> {
705-
return this.buildTransferTransaction(amount, recipient, "public", fee, false, caller, undefined, undefined, undefined, privateKey, offlineQuery);
701+
return this.buildTransferTransaction(amount, recipient, "public", fee, false, undefined, undefined, undefined, privateKey, offlineQuery);
706702
}
707703

708704
/**
@@ -728,7 +724,7 @@ class ProgramManager {
728724
privateKey?: PrivateKey,
729725
offlineQuery?: OfflineQuery
730726
): Promise<Transaction | Error> {
731-
return this.buildTransferTransaction(amount, recipient, "public", fee, false, undefined, undefined, undefined, undefined, privateKey, offlineQuery);
727+
return this.buildTransferTransaction(amount, recipient, "public", fee, false, undefined, undefined, undefined, privateKey, offlineQuery);
732728
}
733729

734730
/**
@@ -739,7 +735,6 @@ class ProgramManager {
739735
* @param {string} transferType The type of transfer to perform - options: 'private', 'privateToPublic', 'public', 'publicToPrivate'
740736
* @param {number} fee The fee to pay for the transfer
741737
* @param {boolean} privateFee Use a private record to pay the fee. If false this will use the account's public credit balance
742-
* @param {string | undefined} caller The caller of the function (if calling transfer_public)
743738
* @param {RecordSearchParams | undefined} recordSearchParams Optional parameters for finding the amount and fee
744739
* records for the transfer transaction
745740
* @param {RecordPlaintext | string} amountRecord Optional amount record to use for the transfer
@@ -766,14 +761,13 @@ class ProgramManager {
766761
transferType: string,
767762
fee: number,
768763
privateFee: boolean,
769-
caller?: string,
770764
recordSearchParams?: RecordSearchParams,
771765
amountRecord?: RecordPlaintext | string,
772766
feeRecord?: RecordPlaintext | string,
773767
privateKey?: PrivateKey,
774768
offlineQuery?: OfflineQuery
775769
): Promise<string | Error> {
776-
const tx = <Transaction>await this.buildTransferTransaction(amount, recipient, transferType, fee, privateFee, caller, recordSearchParams, amountRecord, feeRecord, privateKey, offlineQuery);
770+
const tx = <Transaction>await this.buildTransferTransaction(amount, recipient, transferType, fee, privateFee, recordSearchParams, amountRecord, feeRecord, privateKey, offlineQuery);
777771
return await this.networkClient.submitTransaction(tx);
778772
}
779773

0 commit comments

Comments
 (0)