From 66bf44ca4a91cb9ad6b22ad6daffc2b4b41ee042 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Tue, 10 Sep 2024 23:21:40 -0700 Subject: [PATCH 001/328] feat(zkprogram.ts): change compileProgram method publicInputType from ProvablePure to Provable --- src/lib/proof-system/zkprogram.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 8c5f83da9b..28bda41eee 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -966,7 +966,7 @@ async function compileProgram({ forceRecompile, overrideWrapDomain, }: { - publicInputType: ProvablePure; + publicInputType: Provable; publicOutputType: ProvablePure; methodIntfs: MethodInterface[]; methods: ((...args: any) => unknown)[]; From 3a7c5d6d2a547c1354258b4f941c05d2f7fdb581 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Tue, 10 Sep 2024 23:45:51 -0700 Subject: [PATCH 002/328] feat(zkprogram.ts): change compileProgram method publicOutputType from ProvablePure to Provable --- src/lib/proof-system/zkprogram.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 28bda41eee..73dc089613 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -967,7 +967,7 @@ async function compileProgram({ overrideWrapDomain, }: { publicInputType: Provable; - publicOutputType: ProvablePure; + publicOutputType: Provable; methodIntfs: MethodInterface[]; methods: ((...args: any) => unknown)[]; gates: Gate[][]; From 57e38d258aa56606966a1e4d50b1d13c2e16af2e Mon Sep 17 00:00:00 2001 From: ymekuria Date: Tue, 10 Sep 2024 23:52:52 -0700 Subject: [PATCH 003/328] feat(zkprogram.ts): add createProgramState function to initialize program state for zk programs --- src/lib/proof-system/zkprogram.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 73dc089613..28c412a3e3 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -160,6 +160,10 @@ const FeatureFlags = { fromZkProgramList, }; +function createProgramState() { + +} + async function fromZkProgramList(programs: Array) { let flatMethodIntfs: Array>> = []; From bc711c7a83143478e0faf9e00937ccbf0ff4f540 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 11 Sep 2024 11:41:25 -0700 Subject: [PATCH 004/328] feat(zkprogram.ts): add auxiliaryValues map in createProgramState function --- src/lib/proof-system/zkprogram.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 28c412a3e3..22adc4af35 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -162,6 +162,10 @@ const FeatureFlags = { function createProgramState() { +function createProgramState() { + let auxiliaryValues: Map> = new Map(); + +} } async function fromZkProgramList(programs: Array) { From 0bec8d04388bea6535c5c78b97bae80ba6cd899a Mon Sep 17 00:00:00 2001 From: ymekuria Date: Thu, 12 Sep 2024 10:21:31 -0700 Subject: [PATCH 005/328] feat(zkprogram.ts): add get method to createProgramState --- src/lib/proof-system/zkprogram.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 22adc4af35..ef62908e10 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -160,11 +160,12 @@ const FeatureFlags = { fromZkProgramList, }; -function createProgramState() { - function createProgramState() { let auxiliaryValues: Map> = new Map(); + return { + get: (methodName: string) => { + } } } From b9207360ebc2f0d0d23ba774e73ec33f91b2587d Mon Sep 17 00:00:00 2001 From: ymekuria Date: Thu, 12 Sep 2024 10:31:30 -0700 Subject: [PATCH 006/328] refactor(zkprogram.ts): rename 'get' method to 'getAuxiliaryOutput' for clarity and consistency with its purpose --- src/lib/proof-system/zkprogram.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index ef62908e10..c86ccd95c6 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -163,7 +163,7 @@ const FeatureFlags = { function createProgramState() { let auxiliaryValues: Map> = new Map(); return { - get: (methodName: string) => { + getAuxiliaryOutput: (methodName: string) => { } } From e7c34853e9e208fac4b5aae63d6b24e6c552354c Mon Sep 17 00:00:00 2001 From: ymekuria Date: Thu, 12 Sep 2024 10:33:28 -0700 Subject: [PATCH 007/328] refactor(zkprogram.ts): rename auxiliaryValues variable to methodCache for better clarity and consistency in naming conventions --- src/lib/proof-system/zkprogram.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index c86ccd95c6..b0545b73ff 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -161,7 +161,7 @@ const FeatureFlags = { }; function createProgramState() { - let auxiliaryValues: Map> = new Map(); + let methodCache: Map> = new Map(); return { getAuxiliaryOutput: (methodName: string) => { From 55aafd5ea41bb5a177511f050d0f1aa02de69a45 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Thu, 12 Sep 2024 11:43:43 -0700 Subject: [PATCH 008/328] feat(zkprogram.ts): add setAuxiliaryOutput method to program state for setting auxiliary output values --- src/lib/proof-system/zkprogram.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index b0545b73ff..253e3fd884 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -163,6 +163,8 @@ const FeatureFlags = { function createProgramState() { let methodCache: Map> = new Map(); return { + setAuxiliaryOutput(value: Provable, methodName: string) { + }, getAuxiliaryOutput: (methodName: string) => { } From dc35f8e162cbba021f951bd9ee6c2ef73dbc5be6 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Mon, 16 Sep 2024 00:00:17 -0700 Subject: [PATCH 009/328] feat(zkprogram.ts): get auxiliray output from cache --- src/lib/proof-system/zkprogram.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 253e3fd884..7d3765fd06 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -166,7 +166,8 @@ function createProgramState() { setAuxiliaryOutput(value: Provable, methodName: string) { }, getAuxiliaryOutput: (methodName: string) => { - + let entry = methodCache.get(methodName); + return entry; } } } From 7d9b3c0d8e9ad00a2689492f49bfa536fa977fa9 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Mon, 16 Sep 2024 01:13:15 -0700 Subject: [PATCH 010/328] feat(zkprogram.ts): initialize programState cache --- src/lib/proof-system/zkprogram.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 7d3765fd06..f2a296c243 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -168,7 +168,9 @@ function createProgramState() { getAuxiliaryOutput: (methodName: string) => { let entry = methodCache.get(methodName); return entry; - } + } + + } } @@ -675,6 +677,8 @@ function ZkProgram< } | undefined; + const programState = createProgramState(); + async function compile({ cache = Cache.FileSystemDefault, forceRecompile = false, From 8145573357f1393f3fc335166bdaa7e6d47a891c Mon Sep 17 00:00:00 2001 From: ymekuria Date: Mon, 16 Sep 2024 01:16:11 -0700 Subject: [PATCH 011/328] feat(zkprogram.ts): add programState as a parameter in the compile function --- src/lib/proof-system/zkprogram.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index f2a296c243..186342421a 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -678,7 +678,7 @@ function ZkProgram< | undefined; const programState = createProgramState(); - + async function compile({ cache = Cache.FileSystemDefault, forceRecompile = false, @@ -700,6 +700,7 @@ function ZkProgram< cache, forceRecompile, overrideWrapDomain: config.overrideWrapDomain, + state: programState }); compileOutput = { provers, verify }; From e81eea3a08522616a0d7e3b3d007c3615a13a53d Mon Sep 17 00:00:00 2001 From: ymekuria Date: Mon, 16 Sep 2024 02:06:27 -0700 Subject: [PATCH 012/328] refactor(zkprogram.ts): add optional 'state' parameter to compileProgram function for future use and flexibility --- src/lib/proof-system/zkprogram.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 186342421a..08ec3ae7dc 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -982,6 +982,7 @@ async function compileProgram({ cache, forceRecompile, overrideWrapDomain, + state }: { publicInputType: Provable; publicOutputType: Provable; @@ -992,6 +993,7 @@ async function compileProgram({ cache: Cache; forceRecompile: boolean; overrideWrapDomain?: 0 | 1 | 2; + state?: any }) { await initializeBindings(); if (methodIntfs.length === 0) From 69990386592846110c4e8e95b567ad8d118313ea Mon Sep 17 00:00:00 2001 From: ymekuria Date: Mon, 16 Sep 2024 15:00:01 -0700 Subject: [PATCH 013/328] feat(zkprogram.ts): decompose pure values from auxiliary data type --- src/lib/proof-system/zkprogram.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 08ec3ae7dc..b94458dc01 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -1001,6 +1001,9 @@ async function compileProgram({ Try adding a method to your ZkProgram or SmartContract. If you are using a SmartContract, make sure you are using the @method decorator.`); + // decompose auxilary data type + let pureValues = publicInputType.toFields(publicInputType); + let rules = methodIntfs.map((methodEntry, i) => picklesRuleFromFunction( publicInputType, From dbc9edf22cf67edca1a89ec3721401e88b8bd7cc Mon Sep 17 00:00:00 2001 From: ymekuria Date: Mon, 16 Sep 2024 15:04:45 -0700 Subject: [PATCH 014/328] refactor(zkprogram.ts): pass pure publicInput to picklesFromFunction --- src/lib/proof-system/zkprogram.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index b94458dc01..1d9f840775 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -1002,11 +1002,11 @@ Try adding a method to your ZkProgram or SmartContract. If you are using a SmartContract, make sure you are using the @method decorator.`); // decompose auxilary data type - let pureValues = publicInputType.toFields(publicInputType); - + let pureValues: Field[] = publicInputType.toFields(publicInputType); + let rules = methodIntfs.map((methodEntry, i) => picklesRuleFromFunction( - publicInputType, + pureValues, publicOutputType, methods[i], proofSystemTag, From 0a6e5848d48865ee7cddc26c708d929f42e29e3f Mon Sep 17 00:00:00 2001 From: ymekuria Date: Mon, 16 Sep 2024 15:10:21 -0700 Subject: [PATCH 015/328] feat(zkprogram.ts): decompose auxiliary data from public input --- src/lib/proof-system/zkprogram.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 1d9f840775..ffa0d886ff 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -1004,6 +1004,8 @@ If you are using a SmartContract, make sure you are using the @method decorator. // decompose auxilary data type let pureValues: Field[] = publicInputType.toFields(publicInputType); + let auxilaryPublicInput = publicInputType.toAuxiliary() + let rules = methodIntfs.map((methodEntry, i) => picklesRuleFromFunction( pureValues, From c5ffd545fb35c3aea85579c9ef5e25d658346de3 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Tue, 17 Sep 2024 11:49:01 -0700 Subject: [PATCH 016/328] feat(zkprogram.ts): add setAuxilaryInput method to creatProgramState function --- src/lib/proof-system/zkprogram.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index ffa0d886ff..ba813d8d35 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -165,6 +165,8 @@ function createProgramState() { return { setAuxiliaryOutput(value: Provable, methodName: string) { }, + setAuxilaryInput(value: Provable, methodName: string){}, + getAuxiliaryOutput: (methodName: string) => { let entry = methodCache.get(methodName); return entry; From 3c56586a5e4c4cbe02929072c4be024ffe7de9a1 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Tue, 17 Sep 2024 12:03:46 -0700 Subject: [PATCH 017/328] feat(zkprogram.ts): update method to add auxiliary input data to cache --- src/lib/proof-system/zkprogram.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index ba813d8d35..5d8ed12348 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -165,15 +165,15 @@ function createProgramState() { return { setAuxiliaryOutput(value: Provable, methodName: string) { }, - setAuxilaryInput(value: Provable, methodName: string){}, - - getAuxiliaryOutput: (methodName: string) => { - let entry = methodCache.get(methodName); - return entry; + setAuxilaryInput(value: Provable, methodName: string){ + methodCache.set(methodName, value); + }, + getAuxiliaryOutput: (methodName: string) => { + let entry = methodCache.get(methodName); + return entry; } - - -} + + } } async function fromZkProgramList(programs: Array) { From da4a7c318ca398e354715a722d51a053ed863615 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Tue, 17 Sep 2024 12:08:31 -0700 Subject: [PATCH 018/328] refactor(zkprogram.ts): rename getAuxiliaryOutput to getAuxiliaryInput for consistency and clarity --- src/lib/proof-system/zkprogram.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 5d8ed12348..9de465e35c 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -168,7 +168,7 @@ function createProgramState() { setAuxilaryInput(value: Provable, methodName: string){ methodCache.set(methodName, value); }, - getAuxiliaryOutput: (methodName: string) => { + getAuxilaryInput: (methodName: string) => { let entry = methodCache.get(methodName); return entry; } From 00f62e3da7062572f1478b41e5c1d0b5a45fb5b5 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 18 Sep 2024 01:05:48 -0700 Subject: [PATCH 019/328] refactor(zkprogram.ts): rename publicInputAuxilary variable --- src/lib/proof-system/zkprogram.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 9de465e35c..ad07f77558 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -1003,14 +1003,14 @@ async function compileProgram({ Try adding a method to your ZkProgram or SmartContract. If you are using a SmartContract, make sure you are using the @method decorator.`); - // decompose auxilary data type - let pureValues: Field[] = publicInputType.toFields(publicInputType); + // decompose auxiliary data type + let purePublicInput = publicInputType.toFields(publicInputType); let auxilaryPublicInput = publicInputType.toAuxiliary() - + let rules = methodIntfs.map((methodEntry, i) => picklesRuleFromFunction( - pureValues, + purePublicInput, publicOutputType, methods[i], proofSystemTag, From 4eadd0caa275d2d20f3c304eed591494214a5b44 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 18 Sep 2024 01:20:56 -0700 Subject: [PATCH 020/328] feat(zkprogram.ts): storing of publicInput auxiliary data in cache --- src/lib/proof-system/zkprogram.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index ad07f77558..b10329de5b 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -1007,7 +1007,10 @@ If you are using a SmartContract, make sure you are using the @method decorator. let purePublicInput = publicInputType.toFields(publicInputType); let auxilaryPublicInput = publicInputType.toAuxiliary() - + + // store auxiliary data in cache + state.setAuxilaryInput(auxilaryPublicInput,'auxinput'); + let rules = methodIntfs.map((methodEntry, i) => picklesRuleFromFunction( purePublicInput, From 4cb4b18ed9c33aa8e78974791ed669d83c5ae7f3 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 18 Sep 2024 01:39:25 -0700 Subject: [PATCH 021/328] feat(zkprogram.ts): get auxiliary data from cache --- src/lib/proof-system/zkprogram.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index b10329de5b..741dfab554 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -763,6 +763,8 @@ function ZkProgram< let [publicOutputFields, proof] = MlPair.from(result); let publicOutput = fromFieldConsts(publicOutputType, publicOutputFields); + let publicInputAuxilirary = programState.getAuxilaryInput('auxinput') + return new ProgramProof({ publicInput, publicOutput, @@ -1007,7 +1009,7 @@ If you are using a SmartContract, make sure you are using the @method decorator. let purePublicInput = publicInputType.toFields(publicInputType); let auxilaryPublicInput = publicInputType.toAuxiliary() - + // store auxiliary data in cache state.setAuxilaryInput(auxilaryPublicInput,'auxinput'); From 5d8047b81c2472813f8a9f0d553fad4b6f558e4d Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 18 Sep 2024 01:44:11 -0700 Subject: [PATCH 022/328] feat(zkprogram.ts): recompose the input data to include auxiliary --- src/lib/proof-system/zkprogram.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 741dfab554..d2efc1db9a 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -764,9 +764,13 @@ function ZkProgram< let publicOutput = fromFieldConsts(publicOutputType, publicOutputFields); let publicInputAuxilirary = programState.getAuxilaryInput('auxinput') - + // recompose auxiliary data + let nonPureInput = publicInputType.fromValue({ + publicInput, + publicInputAuxilirary + } ) return new ProgramProof({ - publicInput, + nonPureInput, publicOutput, proof, maxProofsVerified, From e9d936fe1c706d283ba0a384282d86c13bd91948 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 18 Sep 2024 02:13:56 -0700 Subject: [PATCH 023/328] feat(zkprogram.ts): recompose data type from pure values and auxiliary data --- src/lib/proof-system/zkprogram.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index d2efc1db9a..d21ab994aa 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -765,7 +765,7 @@ function ZkProgram< let publicInputAuxilirary = programState.getAuxilaryInput('auxinput') // recompose auxiliary data - let nonPureInput = publicInputType.fromValue({ + let nonPureInput = publicInputType.fromFields({ publicInput, publicInputAuxilirary } ) From de947d46515b5bb9f94ac1ac267776fbcf12b054 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 18 Sep 2024 09:22:47 -0700 Subject: [PATCH 024/328] refactor(zkprogram.ts): rename methodCache to auxInputCache for better clarity and consistency --- src/lib/proof-system/zkprogram.ts | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index d21ab994aa..51b22f81c5 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -161,15 +161,13 @@ const FeatureFlags = { }; function createProgramState() { - let methodCache: Map> = new Map(); + let auxInputCache: Map> = new Map(); return { - setAuxiliaryOutput(value: Provable, methodName: string) { + setAuxilaryInput(value: Provable){ + auxInputCache.set('auxinput', value); }, - setAuxilaryInput(value: Provable, methodName: string){ - methodCache.set(methodName, value); - }, - getAuxilaryInput: (methodName: string) => { - let entry = methodCache.get(methodName); + getAuxilaryInput: () => { + let entry = auxInputCache.get('auxinput'); return entry; } From ef8f3cec88b8ba5ffef47c8b60f79328359deb97 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 18 Sep 2024 10:14:35 -0700 Subject: [PATCH 025/328] feat(zkprogram.ts): reset auxiliary cache --- src/lib/proof-system/zkprogram.ts | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 51b22f81c5..e2411271f8 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -169,7 +169,10 @@ function createProgramState() { getAuxilaryInput: () => { let entry = auxInputCache.get('auxinput'); return entry; - } + }, + resetAuxCache() { + auxInputCache.delete('auxinput'); + }, } } @@ -761,12 +764,17 @@ function ZkProgram< let [publicOutputFields, proof] = MlPair.from(result); let publicOutput = fromFieldConsts(publicOutputType, publicOutputFields); - let publicInputAuxilirary = programState.getAuxilaryInput('auxinput') + let publicInputAuxilirary = programState.getAuxilaryInput() + + // reset auxiliary data + programState.resetAuxCache() // recompose auxiliary data + let nonPureInput = publicInputType.fromFields({ publicInput, publicInputAuxilirary } ) + return new ProgramProof({ nonPureInput, publicOutput, @@ -1013,7 +1021,7 @@ If you are using a SmartContract, make sure you are using the @method decorator. let auxilaryPublicInput = publicInputType.toAuxiliary() // store auxiliary data in cache - state.setAuxilaryInput(auxilaryPublicInput,'auxinput'); + state.setAuxilaryInput(auxilaryPublicInput); let rules = methodIntfs.map((methodEntry, i) => picklesRuleFromFunction( From 16c4ea750624f0321b5c2ee8e7646ca4994049c8 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 18 Sep 2024 10:38:06 -0700 Subject: [PATCH 026/328] feat(program-with-non-pure-input.ts): add a example with nonpure input --- .../zkprogram/program-with-non-pure-input.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/examples/zkprogram/program-with-non-pure-input.ts diff --git a/src/examples/zkprogram/program-with-non-pure-input.ts b/src/examples/zkprogram/program-with-non-pure-input.ts new file mode 100644 index 0000000000..1f8b498a87 --- /dev/null +++ b/src/examples/zkprogram/program-with-non-pure-input.ts @@ -0,0 +1,13 @@ +import { Field, Provable, Struct, ZkProgram, assert } from 'o1js'; + +class MyStruct extends Struct({ + label: String, + value: Field, +}) {} + +let MyProgram = ZkProgram({ + name: 'example-with-non-pure-inputs', + publicOutput: Field, + publicInput: [MyStruct], + methods: {}, +}); From a56602b5efcf96c1aa3a79e91f313ee4eed7df0a Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 18 Sep 2024 10:57:01 -0700 Subject: [PATCH 027/328] refactor(zkprogram.ts): fix typo in function name 'setAuxilaryInput' to 'setAuxiliaryInput' for consistency --- src/lib/proof-system/zkprogram.ts | 43 +++++++++++++++---------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index e2411271f8..40f383b96b 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -163,18 +163,17 @@ const FeatureFlags = { function createProgramState() { let auxInputCache: Map> = new Map(); return { - setAuxilaryInput(value: Provable){ + setAuxilaryInput(value: Provable) { auxInputCache.set('auxinput', value); }, getAuxilaryInput: () => { - let entry = auxInputCache.get('auxinput'); - return entry; + let entry = auxInputCache.get('auxinput'); + return entry; }, resetAuxCache() { auxInputCache.delete('auxinput'); - }, - - } + }, + }; } async function fromZkProgramList(programs: Array) { @@ -680,7 +679,7 @@ function ZkProgram< } | undefined; - const programState = createProgramState(); + const programState = createProgramState(); async function compile({ cache = Cache.FileSystemDefault, @@ -703,7 +702,7 @@ function ZkProgram< cache, forceRecompile, overrideWrapDomain: config.overrideWrapDomain, - state: programState + state: programState, }); compileOutput = { provers, verify }; @@ -764,16 +763,16 @@ function ZkProgram< let [publicOutputFields, proof] = MlPair.from(result); let publicOutput = fromFieldConsts(publicOutputType, publicOutputFields); - let publicInputAuxilirary = programState.getAuxilaryInput() + let publicInputAuxilirary = programState.getAuxilaryInput(); - // reset auxiliary data - programState.resetAuxCache() - // recompose auxiliary data - + // recompose auxiliary data let nonPureInput = publicInputType.fromFields({ - publicInput, - publicInputAuxilirary - } ) + publicInput, + publicInputAuxilirary, + }); + + // reset auxiliary data + programState.resetAuxCache(); return new ProgramProof({ nonPureInput, @@ -996,10 +995,10 @@ async function compileProgram({ cache, forceRecompile, overrideWrapDomain, - state + state, }: { publicInputType: Provable; - publicOutputType: Provable; + publicOutputType: Provable; methodIntfs: MethodInterface[]; methods: ((...args: any) => unknown)[]; gates: Gate[][]; @@ -1007,7 +1006,7 @@ async function compileProgram({ cache: Cache; forceRecompile: boolean; overrideWrapDomain?: 0 | 1 | 2; - state?: any + state?: any; }) { await initializeBindings(); if (methodIntfs.length === 0) @@ -1018,11 +1017,11 @@ If you are using a SmartContract, make sure you are using the @method decorator. // decompose auxiliary data type let purePublicInput = publicInputType.toFields(publicInputType); - let auxilaryPublicInput = publicInputType.toAuxiliary() + let auxilaryPublicInput = publicInputType.toAuxiliary(); - // store auxiliary data in cache + // store auxiliary data in cache state.setAuxilaryInput(auxilaryPublicInput); - + let rules = methodIntfs.map((methodEntry, i) => picklesRuleFromFunction( purePublicInput, From 0130410e51276dcc7fa7cd746b5786869ef5675c Mon Sep 17 00:00:00 2001 From: ymekuria Date: Mon, 7 Oct 2024 21:03:50 -0700 Subject: [PATCH 028/328] chore(bindings): update subproject commit reference to 59eb4c0c3 for consistency --- src/bindings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bindings b/src/bindings index 8e99acc94d..59eb4c0c3c 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit 8e99acc94da892eeb090367844f85d22ecf4f93b +Subproject commit 59eb4c0c3c126819a88624e0445ea31f89c5850a From b9807813602f49c7ed1539370612e5675fa61241 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Mon, 7 Oct 2024 21:23:51 -0700 Subject: [PATCH 029/328] chore(mina): update subproject commit reference to 24c8b2d723fb09d0d7f996b6ac35373dc27084ef --- src/mina | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mina b/src/mina index 9bdaae9990..24c8b2d723 160000 --- a/src/mina +++ b/src/mina @@ -1 +1 @@ -Subproject commit 9bdaae99904c13e3e10841ec6b778e45cdacabfb +Subproject commit 24c8b2d723fb09d0d7f996b6ac35373dc27084ef From 764c68b7705a4053ec17aa3674aff9bd946573e8 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Tue, 8 Oct 2024 00:28:25 -0700 Subject: [PATCH 030/328] feat(zkprogram.ts): update createProgramState function to handle methodCache and auxInputCache --- src/lib/proof-system/zkprogram.ts | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index f79c499884..657b313347 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -162,6 +162,7 @@ const FeatureFlags = { function createProgramState() { let auxInputCache: Map> = new Map(); + let methodCache: Map = new Map(); return { setAuxilaryInput(value: Provable) { auxInputCache.set('auxinput', value); @@ -170,16 +171,7 @@ function createProgramState() { let entry = auxInputCache.get('auxinput'); return entry; }, - resetAuxCache() { - auxInputCache.delete('auxinput'); - }, - }; -} -function createProgramState() { - let methodCache: Map = new Map(); - - return { setAuxiliaryOutput(value: unknown, methodName: string) { methodCache.set(methodName, value); }, @@ -192,6 +184,9 @@ function createProgramState() { reset(methodName: string) { methodCache.delete(methodName); }, + resetAuxCache() { + auxInputCache.delete('auxinput'); + }, }; } From c5fa6f74c75f95c1f8efc8ec19f831a21217a10c Mon Sep 17 00:00:00 2001 From: ymekuria Date: Tue, 8 Oct 2024 15:02:25 -0700 Subject: [PATCH 031/328] feat(zkprogram.ts): decompose auxiliary data from publicInput --- src/lib/proof-system/zkprogram.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 657b313347..a784dd2d32 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -1091,7 +1091,7 @@ Try adding a method to your ZkProgram or SmartContract. If you are using a SmartContract, make sure you are using the @method decorator.`); // decompose auxiliary data type - let purePublicInput = publicInputType.toFields(publicInputType); + let purePublicInput = publicInputType.toFields(publicInput); let auxilaryPublicInput = publicInputType.toAuxiliary(); From 921aee21225291cbf35ea870b486423222e23447 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Tue, 8 Oct 2024 21:45:05 -0700 Subject: [PATCH 032/328] feat(zkprogram.ts): update publicInputType from ProvablePure to Provable --- src/lib/proof-system/zkprogram.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index a784dd2d32..3b8817c57d 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -646,7 +646,7 @@ function ZkProgram< let doProving = true; let methods = config.methods; - let publicInputType: ProvablePure = ProvableType.get( + let publicInputType: Provable = ProvableType.get( config.publicInput ?? Undefined ); let publicOutputType: ProvablePure = ProvableType.get( From c27ab3b68edf478d0adf2ada915df2feee9fb0a7 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Thu, 10 Oct 2024 14:47:43 -0700 Subject: [PATCH 033/328] feat(zkprogram.ts): change publicInputType to Provable from ProvablePure --- src/lib/proof-system/zkprogram.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 3b8817c57d..7c92e4aa7e 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -1222,7 +1222,7 @@ function inCircuitVkHash(inCircuitVk: unknown): Field { } function picklesRuleFromFunction( - publicInputType: ProvablePure, + publicInputType: Provable, publicOutputType: ProvablePure, func: (...args: unknown[]) => unknown, proofSystemTag: { name: string }, From 08574ebf46e84da07e8a61f5bfb2bc74192028cc Mon Sep 17 00:00:00 2001 From: ymekuria Date: Thu, 10 Oct 2024 15:04:40 -0700 Subject: [PATCH 034/328] feat(zkprogram.ts): change publicOutputType in picklesRuleFromFunction to Provable from ProvablePure --- src/lib/proof-system/zkprogram.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 7c92e4aa7e..f7b5a00b98 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -1223,7 +1223,7 @@ function inCircuitVkHash(inCircuitVk: unknown): Field { function picklesRuleFromFunction( publicInputType: Provable, - publicOutputType: ProvablePure, + publicOutputType: Provable, func: (...args: unknown[]) => unknown, proofSystemTag: { name: string }, { From 6077306b0ba3ddff6dc9a5d68cfabf20f4cada51 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Sun, 13 Oct 2024 22:40:32 -0700 Subject: [PATCH 035/328] feat(zkprogram.ts): update picklesRuleFromFunction publicInputType and publicOutputType to use ProvablePure --- src/lib/proof-system/zkprogram.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index f7b5a00b98..3b8817c57d 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -1222,8 +1222,8 @@ function inCircuitVkHash(inCircuitVk: unknown): Field { } function picklesRuleFromFunction( - publicInputType: Provable, - publicOutputType: Provable, + publicInputType: ProvablePure, + publicOutputType: ProvablePure, func: (...args: unknown[]) => unknown, proofSystemTag: { name: string }, { From 7d601c73dfe34aa0071243fc1da6feb15e416ce2 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Mon, 14 Oct 2024 00:12:32 -0700 Subject: [PATCH 036/328] feat(zkprogram.ts): get auxilaryPublicInput from programState cache --- src/lib/proof-system/zkprogram.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 3b8817c57d..1be487cc9c 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -815,6 +815,8 @@ function ZkProgram< programState.reset(methodIntfs[i].methodName); } + let auxilaryPublicInput = programState.getAuxilaryInput(); + let [publicOutputFields, proof] = MlPair.from(result); let publicOutput = fromFieldConsts(publicOutputType, publicOutputFields); From 3a5e476a6126f44e887f54b4433b64706daccf74 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Mon, 14 Oct 2024 00:27:42 -0700 Subject: [PATCH 037/328] feat(zkprogram.ts): recompose non pure data type with program State auxiliary data --- src/lib/proof-system/zkprogram.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 1be487cc9c..f168e18a42 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -817,6 +817,14 @@ function ZkProgram< let auxilaryPublicInput = programState.getAuxilaryInput(); + let nonPurePublicInput; + if (auxilaryPublicInput) { + nonPurePublicInput = publicInputType.fromFields( + publicInput, + auxilaryPublicInput + ); + } + let [publicOutputFields, proof] = MlPair.from(result); let publicOutput = fromFieldConsts(publicOutputType, publicOutputFields); From 437286f22c331bee299ad596f54c40fa6f32cb71 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Tue, 15 Oct 2024 21:59:53 -0700 Subject: [PATCH 038/328] reset(zkprogram.ts): reset the cache --- src/lib/proof-system/zkprogram.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index f168e18a42..c02932ffd1 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -823,6 +823,7 @@ function ZkProgram< publicInput, auxilaryPublicInput ); + programState.resetAuxCache(); } let [publicOutputFields, proof] = MlPair.from(result); From 8b8a9ee10dc07946f57ab99fa733e8f5fb3fe89c Mon Sep 17 00:00:00 2001 From: ymekuria Date: Tue, 15 Oct 2024 22:49:41 -0700 Subject: [PATCH 039/328] feat(zkprogram.ts): add helper function toFieldAndAuxConsts. --- src/lib/proof-system/zkprogram.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index c02932ffd1..e927e5d0ad 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -789,6 +789,8 @@ function ZkProgram< `Try calling \`await program.compile()\` first, this will cache provers in the background.\nIf you compiled your zkProgram with proofs disabled (\`proofsEnabled = false\`), you have to compile it with proofs enabled first.` ); } + + // serialize PublicInput into pure provable let publicInputFields = toFieldConsts(publicInputType, publicInput); let previousProofs = MlArray.to( getPreviousProofsForProver(args, methodIntfs[i]) @@ -1531,6 +1533,8 @@ function toFieldConsts(type: ProvablePure, value: T) { return MlFieldConstArray.to(type.toFields(value)); } +function toFieldAndAuxConsts(type: Provable, value: T) {} + ZkProgram.Proof = function < PublicInputType extends FlexibleProvablePure, PublicOutputType extends FlexibleProvablePure From 0a9a258a2ad8e33580d93dda89b63a972e93fe15 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Tue, 15 Oct 2024 22:53:34 -0700 Subject: [PATCH 040/328] feat(zkprogram.ts): decompose field elements from non pure public input in toFieldAndAuxConsts --- src/lib/proof-system/zkprogram.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index e927e5d0ad..0fc9ae4e66 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -1533,7 +1533,9 @@ function toFieldConsts(type: ProvablePure, value: T) { return MlFieldConstArray.to(type.toFields(value)); } -function toFieldAndAuxConsts(type: Provable, value: T) {} +function toFieldAndAuxConsts(type: Provable, value: T) { + const fields = MlFieldConstArray.to(type.toFields(value)); +} ZkProgram.Proof = function < PublicInputType extends FlexibleProvablePure, From 2d872e7a31f8b96b6d38c57b4a4ad89dc3ae8a81 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Tue, 15 Oct 2024 23:04:31 -0700 Subject: [PATCH 041/328] feat(zkprogram.ts): decompose auxilary data from non pure public input in toFieldAndAuxConsts --- src/lib/proof-system/zkprogram.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 0fc9ae4e66..92f8794ba3 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -1534,7 +1534,8 @@ function toFieldConsts(type: ProvablePure, value: T) { } function toFieldAndAuxConsts(type: Provable, value: T) { - const fields = MlFieldConstArray.to(type.toFields(value)); + let fields = MlFieldConstArray.to(type.toFields(value)); + let aux = type.toAuxiliary(value); } ZkProgram.Proof = function < From ee12afc1f8e5a681f915bd55e423562009238e73 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Tue, 15 Oct 2024 23:06:38 -0700 Subject: [PATCH 042/328] feat(zkprogram.ts)return auxilary data and fields in toFieldAndAuxConsts --- src/lib/proof-system/zkprogram.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 92f8794ba3..51a0f3a07c 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -1536,6 +1536,11 @@ function toFieldConsts(type: ProvablePure, value: T) { function toFieldAndAuxConsts(type: Provable, value: T) { let fields = MlFieldConstArray.to(type.toFields(value)); let aux = type.toAuxiliary(value); + + return { + aux, + fields, + }; } ZkProgram.Proof = function < From eb5676f86d56d88c1003e7999573cb7736281240 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Tue, 15 Oct 2024 23:09:19 -0700 Subject: [PATCH 043/328] refactor(zkprogram.ts): rename variables 'fields' and 'aux' to 'publicInputFields' and 'publicInputAux' for clarity and consistency --- src/lib/proof-system/zkprogram.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 51a0f3a07c..b8320eb8db 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -1534,12 +1534,12 @@ function toFieldConsts(type: ProvablePure, value: T) { } function toFieldAndAuxConsts(type: Provable, value: T) { - let fields = MlFieldConstArray.to(type.toFields(value)); - let aux = type.toAuxiliary(value); + let publicInputFields = MlFieldConstArray.to(type.toFields(value)); + let publicInputAux = type.toAuxiliary(value); return { - aux, - fields, + publicInputFields, + publicInputAux, }; } From 6e0e1e305dd413194a576847aa0b34a1e3965f0d Mon Sep 17 00:00:00 2001 From: ymekuria Date: Tue, 15 Oct 2024 23:13:17 -0700 Subject: [PATCH 044/328] refactor(zkprogram.ts): simplify the toFieldAndAuxConsts function by removing unnecessary variable declarations and directly returning object properties --- src/lib/proof-system/zkprogram.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index b8320eb8db..e0e6c42198 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -1534,12 +1534,9 @@ function toFieldConsts(type: ProvablePure, value: T) { } function toFieldAndAuxConsts(type: Provable, value: T) { - let publicInputFields = MlFieldConstArray.to(type.toFields(value)); - let publicInputAux = type.toAuxiliary(value); - return { - publicInputFields, - publicInputAux, + publicInputFields: MlFieldConstArray.to(type.toFields(value)), + publicInputAux: type.toAuxiliary(value), }; } From 37a09befec1eda0833cb8aacc19ddb09dac515da Mon Sep 17 00:00:00 2001 From: ymekuria Date: Tue, 15 Oct 2024 23:15:43 -0700 Subject: [PATCH 045/328] feat(zkprogram.ts): decompose non pure publicInput into pure field elements and auxiliary data --- src/lib/proof-system/zkprogram.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index e0e6c42198..b0c0484929 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -790,8 +790,11 @@ function ZkProgram< ); } - // serialize PublicInput into pure provable - let publicInputFields = toFieldConsts(publicInputType, publicInput); + // serialize publicInput into pure provable field elements and auxilary data + let { publicInputFields, publicInputAux } = toFieldAndAuxConsts( + publicInputType, + publicInput + ); let previousProofs = MlArray.to( getPreviousProofsForProver(args, methodIntfs[i]) ); From 7491a804f2b4980acab4c3900f3651002ae48a34 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Tue, 15 Oct 2024 23:23:47 -0700 Subject: [PATCH 046/328] feat(zkprogram.ts): set publicInput auxiliary data in cache --- src/lib/proof-system/zkprogram.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index b0c0484929..636dd32896 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -799,6 +799,7 @@ function ZkProgram< getPreviousProofsForProver(args, methodIntfs[i]) ); + programState.setAuxilaryInput(publicInputAux); let id = snarkContext.enter({ witnesses: args, inProver: true }); let result: UnwrapPromise>; try { From 6a2856aa9ec809b5a8d07c9b2229523de3c5d8c5 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Tue, 15 Oct 2024 23:50:46 -0700 Subject: [PATCH 047/328] feat(zkprogram.ts): change type of auxInputCache and methodCache to use 'unknown' for better flexibility and type safety --- src/lib/proof-system/zkprogram.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 636dd32896..7634b0bf49 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -161,10 +161,10 @@ const FeatureFlags = { }; function createProgramState() { - let auxInputCache: Map> = new Map(); + let auxInputCache: Map = new Map(); let methodCache: Map = new Map(); return { - setAuxilaryInput(value: Provable) { + setAuxilaryInput(value: unknown) { auxInputCache.set('auxinput', value); }, getAuxilaryInput: () => { @@ -799,6 +799,7 @@ function ZkProgram< getPreviousProofsForProver(args, methodIntfs[i]) ); + // store publicInput auxilary data in programState cache programState.setAuxilaryInput(publicInputAux); let id = snarkContext.enter({ witnesses: args, inProver: true }); let result: UnwrapPromise>; From b77c5e19784399d7363819f3017c140bdb5c2016 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 16 Oct 2024 00:05:06 -0700 Subject: [PATCH 048/328] feat(zkprogram.ts): add optional 'aux' parameter to 'fromFieldConsts' function for future extensibility and flexibility --- src/lib/proof-system/zkprogram.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 7634b0bf49..21a90fea00 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -1531,7 +1531,11 @@ function toFieldVars(type: ProvablePure, value: T) { return MlFieldArray.to(type.toFields(value)); } -function fromFieldConsts(type: ProvablePure, fields: MlFieldConstArray) { +function fromFieldConsts( + type: ProvablePure, + fields: MlFieldConstArray, + aux?: unknown +) { return type.fromFields(MlFieldConstArray.from(fields)); } function toFieldConsts(type: ProvablePure, value: T) { From df972be7b96644fa410575751e57c173906e7306 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 16 Oct 2024 00:20:10 -0700 Subject: [PATCH 049/328] refactor(zkprogram.ts): update function signature and parameter types for better clarity and consistency --- src/lib/proof-system/zkprogram.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 21a90fea00..08350aa8a7 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -1532,11 +1532,11 @@ function toFieldVars(type: ProvablePure, value: T) { } function fromFieldConsts( - type: ProvablePure, + type: Provable, fields: MlFieldConstArray, - aux?: unknown + aux?: any[] ) { - return type.fromFields(MlFieldConstArray.from(fields)); + return type.fromFields(MlFieldConstArray.from(fields), aux); } function toFieldConsts(type: ProvablePure, value: T) { return MlFieldConstArray.to(type.toFields(value)); From c6a8260e7a0c2e98a1de34b3faa0ffa99b2e3eb2 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 16 Oct 2024 00:42:20 -0700 Subject: [PATCH 050/328] feat(zkprogram.ts): add fromFieldAndAuxConsts helper function --- src/lib/proof-system/zkprogram.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 08350aa8a7..81dfa64515 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -1538,6 +1538,15 @@ function fromFieldConsts( ) { return type.fromFields(MlFieldConstArray.from(fields), aux); } + +function fromFieldAndAuxConsts( + type: Provable, + fields: MlFieldConstArray, + aux: any[] +) { + return type.fromFields(MlFieldConstArray.from(fields), aux); +} + function toFieldConsts(type: ProvablePure, value: T) { return MlFieldConstArray.to(type.toFields(value)); } From efa1379e4e2a55bf8d12392ad04aed5ffe7ec4ab Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 16 Oct 2024 00:47:36 -0700 Subject: [PATCH 051/328] refactor(zkprogram.ts): simplify fromFieldConsts function parameters to improve readability and maintainability --- src/lib/proof-system/zkprogram.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 81dfa64515..0038e09a4b 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -1531,12 +1531,8 @@ function toFieldVars(type: ProvablePure, value: T) { return MlFieldArray.to(type.toFields(value)); } -function fromFieldConsts( - type: Provable, - fields: MlFieldConstArray, - aux?: any[] -) { - return type.fromFields(MlFieldConstArray.from(fields), aux); +function fromFieldConsts(type: ProvablePure, fields: MlFieldConstArray) { + return type.fromFields(MlFieldConstArray.from(fields)); } function fromFieldAndAuxConsts( From 062d3137ffb0087b8f3beeca5200007f39b93195 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 16 Oct 2024 00:57:27 -0700 Subject: [PATCH 052/328] feat(zkprogram.ts): add conditional check before storing publicInput auxilary data in programState cache --- src/lib/proof-system/zkprogram.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 0038e09a4b..3f45bac832 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -799,8 +799,10 @@ function ZkProgram< getPreviousProofsForProver(args, methodIntfs[i]) ); - // store publicInput auxilary data in programState cache - programState.setAuxilaryInput(publicInputAux); + if (publicInputAux) { + // store publicInput auxilary data in programState cache + programState.setAuxilaryInput(publicInputAux); + } let id = snarkContext.enter({ witnesses: args, inProver: true }); let result: UnwrapPromise>; try { From e9aa3eb641b54a1f3128450efc29e49ce9f4fe88 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 16 Oct 2024 01:18:08 -0700 Subject: [PATCH 053/328] feat(zkprogram.ts): add conditional to recompose non pure data type if there is auxilary input --- src/lib/proof-system/zkprogram.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 3f45bac832..08ce2f3171 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -834,8 +834,14 @@ function ZkProgram< ); programState.resetAuxCache(); } - let [publicOutputFields, proof] = MlPair.from(result); + if (publicInputAux) { + fromFieldAndAuxConsts( + publicOutputType, + publicOutputFields, + publicInputAux + ); + } let publicOutput = fromFieldConsts(publicOutputType, publicOutputFields); return { From f741f981d35cb9275c64258303a3cdc9820e1da9 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 16 Oct 2024 01:24:45 -0700 Subject: [PATCH 054/328] feat(zkprogram.ts): refactor public output generation logic to handle both public input auxiliary constants and regular public output fields --- src/lib/proof-system/zkprogram.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 08ce2f3171..1c81b3d88c 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -834,15 +834,18 @@ function ZkProgram< ); programState.resetAuxCache(); } + + let publicOutput; let [publicOutputFields, proof] = MlPair.from(result); if (publicInputAux) { - fromFieldAndAuxConsts( + publicOutput = fromFieldAndAuxConsts( publicOutputType, publicOutputFields, publicInputAux ); + } else { + publicOutput = fromFieldConsts(publicOutputType, publicOutputFields); } - let publicOutput = fromFieldConsts(publicOutputType, publicOutputFields); return { proof: new ProgramProof({ From ee7165457e0e3f6d4a5cff5f3f21c50d2c2fff0a Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 16 Oct 2024 01:26:56 -0700 Subject: [PATCH 055/328] feat(zkprogram.ts): clear auxiliary cache before generating proof --- src/lib/proof-system/zkprogram.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 1c81b3d88c..ac466f3edc 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -843,6 +843,7 @@ function ZkProgram< publicOutputFields, publicInputAux ); + programState.resetAuxCache(); } else { publicOutput = fromFieldConsts(publicOutputType, publicOutputFields); } From e65064f1d1d069aa5f5ad958f100ac25a441781a Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 16 Oct 2024 01:27:51 -0700 Subject: [PATCH 056/328] refactor(zkprogram.ts): remove unused variables and unnecessary code for better code readability and maintainability --- src/lib/proof-system/zkprogram.ts | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index ac466f3edc..bc5381c581 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -824,17 +824,6 @@ function ZkProgram< programState.reset(methodIntfs[i].methodName); } - let auxilaryPublicInput = programState.getAuxilaryInput(); - - let nonPurePublicInput; - if (auxilaryPublicInput) { - nonPurePublicInput = publicInputType.fromFields( - publicInput, - auxilaryPublicInput - ); - programState.resetAuxCache(); - } - let publicOutput; let [publicOutputFields, proof] = MlPair.from(result); if (publicInputAux) { From 5347ac3b4419a961bf41f1115000784a2dfedb01 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 16 Oct 2024 01:31:21 -0700 Subject: [PATCH 057/328] feat(zkprogram.ts): update publicInputType in picklesRuleFromFunction --- src/lib/proof-system/zkprogram.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index bc5381c581..173fc203bc 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -1119,7 +1119,7 @@ If you are using a SmartContract, make sure you are using the @method decorator. let rules = methodIntfs.map((methodEntry, i) => picklesRuleFromFunction( - purePublicInput, + publicInputType, publicOutputType, methods[i], proofSystemTag, From 5e68a1173481c5d75976b48c9e9f429867f950c7 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 16 Oct 2024 01:33:29 -0700 Subject: [PATCH 058/328] refactor(zkprogram.ts): remove unused code related to decomposing auxiliary data type and storing it in cache --- src/lib/proof-system/zkprogram.ts | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 173fc203bc..bf20ead481 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -1109,14 +1109,6 @@ async function compileProgram({ Try adding a method to your ZkProgram or SmartContract. If you are using a SmartContract, make sure you are using the @method decorator.`); - // decompose auxiliary data type - let purePublicInput = publicInputType.toFields(publicInput); - - let auxilaryPublicInput = publicInputType.toAuxiliary(); - - // store auxiliary data in cache - state.setAuxilaryInput(auxilaryPublicInput); - let rules = methodIntfs.map((methodEntry, i) => picklesRuleFromFunction( publicInputType, From b3521e9f08c78e787c18c792a71e3af638e3f198 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 16 Oct 2024 01:38:20 -0700 Subject: [PATCH 059/328] feat(zkprogram.ts): update ProofBase class publicInputType and publicOutputType to use FlexibleProvable type for better type safety and clarity --- src/lib/proof-system/zkprogram.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index bf20ead481..8b4c3b8b8c 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -245,8 +245,8 @@ async function featureFlagsfromFlatMethodIntfs( } class ProofBase { - static publicInputType: FlexibleProvablePure = undefined as any; - static publicOutputType: FlexibleProvablePure = undefined as any; + static publicInputType: FlexibleProvable = undefined as any; + static publicOutputType: FlexibleProvable = undefined as any; static tag: () => { name: string } = () => { throw Error( `You cannot use the \`Proof\` class directly. Instead, define a subclass:\n` + From ce84a0d9e50d9c6fdb09a748a1b7cd6e72561794 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 16 Oct 2024 01:39:56 -0700 Subject: [PATCH 060/328] feat(zkprogram.ts): update analyzeMethods publicInputType parameter type from ProvablePure to Provable for consistency and clarity --- src/lib/proof-system/zkprogram.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 8b4c3b8b8c..21fe6a2972 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -1205,7 +1205,7 @@ If you are using a SmartContract, make sure you are using the @method decorator. } function analyzeMethod( - publicInputType: ProvablePure, + publicInputType: Provable, methodIntf: MethodInterface, method: (...args: any) => unknown ) { From 3c8d0304ebaad16749332c035113c7f3267e0e61 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 16 Oct 2024 01:41:49 -0700 Subject: [PATCH 061/328] feat(zkprogram.ts): update toFieldConst parameter type from ProvablePure to Provable for better clarity and consistency --- src/lib/proof-system/zkprogram.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 21fe6a2972..7994395556 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -1536,7 +1536,7 @@ function fromFieldAndAuxConsts( return type.fromFields(MlFieldConstArray.from(fields), aux); } -function toFieldConsts(type: ProvablePure, value: T) { +function toFieldConsts(type: Provable, value: T) { return MlFieldConstArray.to(type.toFields(value)); } From d0885f218b43edb670d625fdc1e405709393054b Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 16 Oct 2024 01:44:36 -0700 Subject: [PATCH 062/328] feat(zkprogram.ts): update PicklesRuleFromFunction publicInputType and publicOutputType parameters to ProvablePure to Provable for --- src/lib/proof-system/zkprogram.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 7994395556..669899a96b 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -1233,8 +1233,8 @@ function inCircuitVkHash(inCircuitVk: unknown): Field { } function picklesRuleFromFunction( - publicInputType: ProvablePure, - publicOutputType: ProvablePure, + publicInputType: Provable, + publicOutputType: Provable, func: (...args: unknown[]) => unknown, proofSystemTag: { name: string }, { From 84df9aad0a57ea6de399dded322b0d6ccdb41d8f Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 16 Oct 2024 08:56:41 -0700 Subject: [PATCH 063/328] feat(zkprogram.ts): update config publicInputType to ProvableType --- src/lib/proof-system/zkprogram.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 669899a96b..6e2a3f81da 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -569,8 +569,8 @@ let SideloadedTag = { function ZkProgram< Config extends { - publicInput?: ProvableTypePure; - publicOutput?: ProvableTypePure; + publicInput?: ProvableType; + publicOutput?: ProvableType; methods: { [I in string]: { privateInputs: Tuple; From 77146bfb4b74a89ee79fd02f006fcf0acb604d46 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 16 Oct 2024 09:28:02 -0700 Subject: [PATCH 064/328] feat(zkprogram.ts): update config publicOutputType to Provable --- src/lib/proof-system/zkprogram.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 6e2a3f81da..8391ff4799 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -649,7 +649,7 @@ function ZkProgram< let publicInputType: Provable = ProvableType.get( config.publicInput ?? Undefined ); - let publicOutputType: ProvablePure = ProvableType.get( + let publicOutputType: Provable = ProvableType.get( config.publicOutput ?? Void ); From e05f3c17985d648d52b9dd7f03a6ace36cadd558 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 16 Oct 2024 09:53:17 -0700 Subject: [PATCH 065/328] feat(zkprogram.ts): temp update to fromFieldConsts type --- src/lib/proof-system/zkprogram.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 8391ff4799..e274308fe9 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -1524,7 +1524,7 @@ function toFieldVars(type: ProvablePure, value: T) { return MlFieldArray.to(type.toFields(value)); } -function fromFieldConsts(type: ProvablePure, fields: MlFieldConstArray) { +function fromFieldConsts(type: any, fields: MlFieldConstArray) { return type.fromFields(MlFieldConstArray.from(fields)); } From dc2b2cbeb017152d7577bb04d1d6567b65433204 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Fri, 18 Oct 2024 17:32:16 -0600 Subject: [PATCH 066/328] refactor(program-with-non-pure-input.ts): update publicInput property in to accept a non pure MyStruct instance instead of an array of MyStruct instances --- src/examples/zkprogram/program-with-non-pure-input.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/examples/zkprogram/program-with-non-pure-input.ts b/src/examples/zkprogram/program-with-non-pure-input.ts index 1f8b498a87..81b494f9e4 100644 --- a/src/examples/zkprogram/program-with-non-pure-input.ts +++ b/src/examples/zkprogram/program-with-non-pure-input.ts @@ -8,6 +8,6 @@ class MyStruct extends Struct({ let MyProgram = ZkProgram({ name: 'example-with-non-pure-inputs', publicOutput: Field, - publicInput: [MyStruct], + publicInput: MyStruct, methods: {}, }); From 0355f674c134e63a1ef4243ec04f9d1a4b5f3a87 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Fri, 18 Oct 2024 17:41:34 -0600 Subject: [PATCH 067/328] feat(zkprogram.ts): update publicIntype parameter in fromFieldVars function to any for flexibility and compatibility with different types of inputs --- src/lib/proof-system/zkprogram.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index e274308fe9..e2ac02d8a1 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -1517,7 +1517,7 @@ function getMaxProofsVerified(methodIntfs: MethodInterface[]) { ) as any as 0 | 1 | 2; } -function fromFieldVars(type: ProvablePure, fields: MlFieldArray) { +function fromFieldVars(type: any, fields: MlFieldArray) { return type.fromFields(MlFieldArray.from(fields)); } function toFieldVars(type: ProvablePure, value: T) { From 8b8c1206c6a079540f8497681edcf4c43cf2afca Mon Sep 17 00:00:00 2001 From: ymekuria Date: Fri, 18 Oct 2024 23:35:59 -0600 Subject: [PATCH 068/328] feat(program-with-non-pure-input.ts): add 'baseCase' method to example --- src/examples/zkprogram/program-with-non-pure-input.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/examples/zkprogram/program-with-non-pure-input.ts b/src/examples/zkprogram/program-with-non-pure-input.ts index 81b494f9e4..6094434c62 100644 --- a/src/examples/zkprogram/program-with-non-pure-input.ts +++ b/src/examples/zkprogram/program-with-non-pure-input.ts @@ -7,7 +7,12 @@ class MyStruct extends Struct({ let MyProgram = ZkProgram({ name: 'example-with-non-pure-inputs', - publicOutput: Field, publicInput: MyStruct, - methods: {}, + + methods: { + baseCase: { + privateInputs: [], + async method(input: MyStruct) {}, + }, + }, }); From 1fbe24f8dc1d2d33535811da4a597bb79ab341ab Mon Sep 17 00:00:00 2001 From: ymekuria Date: Fri, 18 Oct 2024 23:42:23 -0600 Subject: [PATCH 069/328] feat(program-with-non-pure-input.ts): compile zkprogram --- src/examples/zkprogram/program-with-non-pure-input.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/examples/zkprogram/program-with-non-pure-input.ts b/src/examples/zkprogram/program-with-non-pure-input.ts index 6094434c62..c3e473a1c7 100644 --- a/src/examples/zkprogram/program-with-non-pure-input.ts +++ b/src/examples/zkprogram/program-with-non-pure-input.ts @@ -16,3 +16,7 @@ let MyProgram = ZkProgram({ }, }, }); + +console.log('compiling MyProgram...'); +await MyProgram.compile(); +console.log('compile done'); From 36b92fc941a469296012888ad9b6049eca647f0c Mon Sep 17 00:00:00 2001 From: ymekuria Date: Fri, 18 Oct 2024 23:58:47 -0600 Subject: [PATCH 070/328] feat(program-with-non-pure-input.ts): update baseCase method to return non pure publicOutput --- src/examples/zkprogram/program-with-non-pure-input.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/examples/zkprogram/program-with-non-pure-input.ts b/src/examples/zkprogram/program-with-non-pure-input.ts index c3e473a1c7..f215f894d4 100644 --- a/src/examples/zkprogram/program-with-non-pure-input.ts +++ b/src/examples/zkprogram/program-with-non-pure-input.ts @@ -8,11 +8,16 @@ class MyStruct extends Struct({ let MyProgram = ZkProgram({ name: 'example-with-non-pure-inputs', publicInput: MyStruct, + publicOutput: MyStruct, methods: { baseCase: { privateInputs: [], - async method(input: MyStruct) {}, + async method(input: MyStruct) { + return { + publicOutput: input, + }; + }, }, }, }); From a9ab6e1a2890809588c7efac0d635bccacee1948 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Sat, 19 Oct 2024 00:11:59 -0600 Subject: [PATCH 071/328] feat(program-with-non-pure-input.ts): add invoke basecase method with non pure input in example --- src/examples/zkprogram/program-with-non-pure-input.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/examples/zkprogram/program-with-non-pure-input.ts b/src/examples/zkprogram/program-with-non-pure-input.ts index f215f894d4..d972f64896 100644 --- a/src/examples/zkprogram/program-with-non-pure-input.ts +++ b/src/examples/zkprogram/program-with-non-pure-input.ts @@ -25,3 +25,6 @@ let MyProgram = ZkProgram({ console.log('compiling MyProgram...'); await MyProgram.compile(); console.log('compile done'); + +let input = new MyStruct({ label: 'input', value: Field(5) }); +let result = await MyProgram.baseCase(input); From 9f5f39b6a6251a12103a47c3a255a359ee686c28 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Sat, 19 Oct 2024 00:23:36 -0600 Subject: [PATCH 072/328] feat(program-with-non-pure-input.ts): add verification step after running MyProgram to ensure proof validity --- src/examples/zkprogram/program-with-non-pure-input.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/examples/zkprogram/program-with-non-pure-input.ts b/src/examples/zkprogram/program-with-non-pure-input.ts index d972f64896..0a1224113c 100644 --- a/src/examples/zkprogram/program-with-non-pure-input.ts +++ b/src/examples/zkprogram/program-with-non-pure-input.ts @@ -28,3 +28,7 @@ console.log('compile done'); let input = new MyStruct({ label: 'input', value: Field(5) }); let result = await MyProgram.baseCase(input); +let ok = await MyProgram.verify(result.proof); + +console.log('ok', ok); +assert(ok, 'proof not valid!'); From df1f6156726ce72a7b3e32c73168f86a77f7c845 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Sat, 19 Oct 2024 01:09:30 -0600 Subject: [PATCH 073/328] feat(zkprogram.ts): add check if publicInput has aux data --- src/lib/proof-system/zkprogram.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index e2ac02d8a1..40280d1bcc 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -165,10 +165,12 @@ function createProgramState() { let methodCache: Map = new Map(); return { setAuxilaryInput(value: unknown) { + console.log('setAuxilaryInput with', value); auxInputCache.set('auxinput', value); }, getAuxilaryInput: () => { let entry = auxInputCache.get('auxinput'); + console.log('getAuxilaryInput', entry); return entry; }, @@ -790,11 +792,19 @@ function ZkProgram< ); } + let publicInputAuxExists = + publicInputType.toAuxiliary(publicInput).length !== 0; + // serialize publicInput into pure provable field elements and auxilary data let { publicInputFields, publicInputAux } = toFieldAndAuxConsts( publicInputType, publicInput ); + + console.log( + 'publicInputAux after calling toFieldAndAuxConsts', + publicInputAux + ); let previousProofs = MlArray.to( getPreviousProofsForProver(args, methodIntfs[i]) ); @@ -827,13 +837,17 @@ function ZkProgram< let publicOutput; let [publicOutputFields, proof] = MlPair.from(result); if (publicInputAux) { + console.log('if publicInputAux', publicInputAux); publicOutput = fromFieldAndAuxConsts( publicOutputType, publicOutputFields, publicInputAux ); + + console.log('publicOutput after fromFieldAndAuxConsts', publicOutput); programState.resetAuxCache(); } else { + // create public output when public input is pure publicOutput = fromFieldConsts(publicOutputType, publicOutputFields); } From 67854f0a48eef9d1855e1e784defd5cd656d3deb Mon Sep 17 00:00:00 2001 From: ymekuria Date: Sat, 19 Oct 2024 02:41:36 -0600 Subject: [PATCH 074/328] feat(zkprogram.ts): check if public input has aux data before serialization --- src/lib/proof-system/zkprogram.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 40280d1bcc..42b2ded8a5 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -795,11 +795,14 @@ function ZkProgram< let publicInputAuxExists = publicInputType.toAuxiliary(publicInput).length !== 0; + let publicInputFields, publicInputAux; + if (publicInputAuxExists) { + ({ publicInputFields, publicInputAux } = toFieldAndAuxConsts( + publicInputType, + publicInput + )); + } // serialize publicInput into pure provable field elements and auxilary data - let { publicInputFields, publicInputAux } = toFieldAndAuxConsts( - publicInputType, - publicInput - ); console.log( 'publicInputAux after calling toFieldAndAuxConsts', From 146c783ad577665bbc9da11ed3ddb6a0fee49f17 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Sat, 19 Oct 2024 02:50:27 -0600 Subject: [PATCH 075/328] feat(zkprogram.ts): check if public input aux data exists before storing --- src/lib/proof-system/zkprogram.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 42b2ded8a5..6e19e1c7c2 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -797,12 +797,15 @@ function ZkProgram< let publicInputFields, publicInputAux; if (publicInputAuxExists) { + // serialize publicInput into pure provable field elements and auxilary data ({ publicInputFields, publicInputAux } = toFieldAndAuxConsts( publicInputType, publicInput )); + + // store publicInput auxilary data in programState cache + programState.setAuxilaryInput(publicInputAux); } - // serialize publicInput into pure provable field elements and auxilary data console.log( 'publicInputAux after calling toFieldAndAuxConsts', @@ -813,8 +816,6 @@ function ZkProgram< ); if (publicInputAux) { - // store publicInput auxilary data in programState cache - programState.setAuxilaryInput(publicInputAux); } let id = snarkContext.enter({ witnesses: args, inProver: true }); let result: UnwrapPromise>; From e4c3fb3776a33873660fbe9654c0c02befb3c502 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Sat, 19 Oct 2024 02:55:36 -0600 Subject: [PATCH 076/328] feat(zkprogram.ts): return publicInputFields when no aux data --- src/lib/proof-system/zkprogram.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 6e19e1c7c2..819a78e501 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -805,6 +805,8 @@ function ZkProgram< // store publicInput auxilary data in programState cache programState.setAuxilaryInput(publicInputAux); + } else { + publicInputFields = toFieldConsts(publicInputType, publicInput); } console.log( From a836f0e95e599f4580d95c6dafcdf217c76bc620 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Sat, 19 Oct 2024 15:09:49 -0600 Subject: [PATCH 077/328] feature(zkprogram.ts): use fromFieldAndAuxConsts function in case when no aux data --- src/lib/proof-system/zkprogram.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 819a78e501..1f59cb30ec 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -854,7 +854,10 @@ function ZkProgram< programState.resetAuxCache(); } else { // create public output when public input is pure - publicOutput = fromFieldConsts(publicOutputType, publicOutputFields); + publicOutput = fromFieldAndAuxConsts( + publicOutputType, + publicOutputFields + ); } return { @@ -1551,7 +1554,7 @@ function fromFieldConsts(type: any, fields: MlFieldConstArray) { function fromFieldAndAuxConsts( type: Provable, fields: MlFieldConstArray, - aux: any[] + aux: any[] = [] ) { return type.fromFields(MlFieldConstArray.from(fields), aux); } From 519c301980b7fdda44688118881bca36bcac4e26 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Sun, 20 Oct 2024 00:39:12 -0600 Subject: [PATCH 078/328] feat(zkprogram.ts): update type parameter in fromFieldVars to Provable type --- src/lib/proof-system/zkprogram.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 1f59cb30ec..430c5d5f20 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -1540,7 +1540,7 @@ function getMaxProofsVerified(methodIntfs: MethodInterface[]) { ) as any as 0 | 1 | 2; } -function fromFieldVars(type: any, fields: MlFieldArray) { +function fromFieldVars(type: Provable, fields: MlFieldArray) { return type.fromFields(MlFieldArray.from(fields)); } function toFieldVars(type: ProvablePure, value: T) { From f661d9168a3604b8c4a65661eada0ff22ac1ee8e Mon Sep 17 00:00:00 2001 From: ymekuria Date: Sun, 20 Oct 2024 00:56:14 -0600 Subject: [PATCH 079/328] feat(zkprogram.ts): update fromFieldVars function to include an empty aux value as second argument to fromFields --- src/lib/proof-system/zkprogram.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 430c5d5f20..caecf5905f 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -1541,7 +1541,7 @@ function getMaxProofsVerified(methodIntfs: MethodInterface[]) { } function fromFieldVars(type: Provable, fields: MlFieldArray) { - return type.fromFields(MlFieldArray.from(fields)); + return type.fromFields(MlFieldArray.from(fields), []); } function toFieldVars(type: ProvablePure, value: T) { return MlFieldArray.to(type.toFields(value)); From 3914a7d4899a9c13e310999e8831ec198006d6da Mon Sep 17 00:00:00 2001 From: ymekuria Date: Sun, 20 Oct 2024 01:44:21 -0600 Subject: [PATCH 080/328] refactor(zkprogram.ts): remove unnecessary if statement and add missing newline before function declaration --- src/lib/proof-system/zkprogram.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index caecf5905f..75f4bcb94d 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -817,8 +817,6 @@ function ZkProgram< getPreviousProofsForProver(args, methodIntfs[i]) ); - if (publicInputAux) { - } let id = snarkContext.enter({ witnesses: args, inProver: true }); let result: UnwrapPromise>; try { @@ -1543,6 +1541,7 @@ function getMaxProofsVerified(methodIntfs: MethodInterface[]) { function fromFieldVars(type: Provable, fields: MlFieldArray) { return type.fromFields(MlFieldArray.from(fields), []); } + function toFieldVars(type: ProvablePure, value: T) { return MlFieldArray.to(type.toFields(value)); } From 4647ffbe21be13d9f69421b859b7f852bab6baa3 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Sun, 20 Oct 2024 01:47:14 -0600 Subject: [PATCH 081/328] refactor(zkprogram.ts): rename use 'publicInputAuxExists' check --- src/lib/proof-system/zkprogram.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 75f4bcb94d..b443b922e2 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -840,7 +840,7 @@ function ZkProgram< let publicOutput; let [publicOutputFields, proof] = MlPair.from(result); - if (publicInputAux) { + if (publicInputAuxExists) { console.log('if publicInputAux', publicInputAux); publicOutput = fromFieldAndAuxConsts( publicOutputType, From b5eeee5f7cd9b4fcc1a1860e6b1097d5b9c8145c Mon Sep 17 00:00:00 2001 From: ymekuria Date: Sun, 20 Oct 2024 14:28:09 -0600 Subject: [PATCH 082/328] refactor(zkprogram.ts): remove unnecessary console.log statements for better code cleanliness and readability --- src/lib/proof-system/zkprogram.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index b443b922e2..8d991cd949 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -809,10 +809,6 @@ function ZkProgram< publicInputFields = toFieldConsts(publicInputType, publicInput); } - console.log( - 'publicInputAux after calling toFieldAndAuxConsts', - publicInputAux - ); let previousProofs = MlArray.to( getPreviousProofsForProver(args, methodIntfs[i]) ); @@ -840,8 +836,8 @@ function ZkProgram< let publicOutput; let [publicOutputFields, proof] = MlPair.from(result); - if (publicInputAuxExists) { - console.log('if publicInputAux', publicInputAux); + if (publicInputAux) { + publicInputAux = programState.getAuxilaryInput(); publicOutput = fromFieldAndAuxConsts( publicOutputType, publicOutputFields, From 8cbe588df4debc15aa553777a9cd6f2c0d44b636 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Sun, 20 Oct 2024 20:53:48 -0600 Subject: [PATCH 083/328] feat(zkprogram.ts): change the type of auxInputCache values from unknown to any[] for better type safety and clarity --- src/lib/proof-system/zkprogram.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 8d991cd949..3e2795c78a 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -161,7 +161,7 @@ const FeatureFlags = { }; function createProgramState() { - let auxInputCache: Map = new Map(); + let auxInputCache: Map = new Map(); let methodCache: Map = new Map(); return { setAuxilaryInput(value: unknown) { From bb505961094b9b57845def60a1bdd74c01de9bac Mon Sep 17 00:00:00 2001 From: ymekuria Date: Sun, 20 Oct 2024 20:54:36 -0600 Subject: [PATCH 084/328] feat(zkprogram.ts): change parameter type of setAuxilaryInput function in programState cache from unknown to any[] for better type safety and clarity --- src/lib/proof-system/zkprogram.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 3e2795c78a..fe3c62fbf1 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -164,7 +164,7 @@ function createProgramState() { let auxInputCache: Map = new Map(); let methodCache: Map = new Map(); return { - setAuxilaryInput(value: unknown) { + setAuxilaryInput(value: any[]) { console.log('setAuxilaryInput with', value); auxInputCache.set('auxinput', value); }, From 974dfb01a2ee9a121f0ce0d0c283d130b76d4ee7 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Sun, 20 Oct 2024 21:22:42 -0600 Subject: [PATCH 085/328] feat(zkprogram.ts): check if the publicInput has aux data before getting it from programState --- src/lib/proof-system/zkprogram.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index fe3c62fbf1..4d20f90122 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -836,7 +836,7 @@ function ZkProgram< let publicOutput; let [publicOutputFields, proof] = MlPair.from(result); - if (publicInputAux) { + if (publicInputAuxExists) { publicInputAux = programState.getAuxilaryInput(); publicOutput = fromFieldAndAuxConsts( publicOutputType, From cb41aaf2cfd81dba379eada6c4212efb6c193f74 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Mon, 21 Oct 2024 00:29:23 -0600 Subject: [PATCH 086/328] chore(CHANGELOG-v2.md): update changelog --- CHANGELOG-v2.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG-v2.md b/CHANGELOG-v2.md index 43e845c424..36efaddd12 100644 --- a/CHANGELOG-v2.md +++ b/CHANGELOG-v2.md @@ -34,6 +34,8 @@ Showing all changes since the last release (v.1.5.0) ### Added +-`zkProgram` to support non-pure provable types as inputs and outputs https://github.com/o1-labs/o1js/pull/1828 + - New method `toCanonical()` in the `Provable` interface to protect against incompleteness of certain operations on malicious witness inputs https://github.com/o1-labs/o1js/pull/1759 - `divMod64()` division modulo 2^64 that returns the remainder and quotient of the operation - `addMod64()` addition modulo 2^64 From 4390dafb66087b9b334e78704798a50e15c3bc3d Mon Sep 17 00:00:00 2001 From: ymekuria Date: Mon, 21 Oct 2024 00:39:21 -0600 Subject: [PATCH 087/328] feat(zkprogram.ts): improve cache error handling in get by throwing an error when auxiliary input is not defined --- src/lib/proof-system/zkprogram.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 4d20f90122..b04ffe3d23 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -171,6 +171,7 @@ function createProgramState() { getAuxilaryInput: () => { let entry = auxInputCache.get('auxinput'); console.log('getAuxilaryInput', entry); + if (entry === undefined) throw Error(`Auxiliary input not defined`); return entry; }, @@ -1346,7 +1347,7 @@ function picklesRuleFromFunction( Pickles.sideLoaded.inCircuit(computedTag, circuitVk); }); - // if the public output is empty, we don't evaluate `toFields(result)` to allow the function to return something else in that case + // if the output is empty, we don't evaluate `toFields(result)` to allow the function to return something else in that case let hasPublicOutput = publicOutputType.sizeInFields() !== 0; let publicOutput = hasPublicOutput ? publicOutputType.toFields(result.publicOutput) From 98386220edab427b783821ad6f3761e52f4c1806 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Mon, 21 Oct 2024 00:45:32 -0600 Subject: [PATCH 088/328] refactor(zkprogram.ts): remove logs --- src/lib/proof-system/zkprogram.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index b04ffe3d23..962ce227b0 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -165,12 +165,10 @@ function createProgramState() { let methodCache: Map = new Map(); return { setAuxilaryInput(value: any[]) { - console.log('setAuxilaryInput with', value); auxInputCache.set('auxinput', value); }, getAuxilaryInput: () => { let entry = auxInputCache.get('auxinput'); - console.log('getAuxilaryInput', entry); if (entry === undefined) throw Error(`Auxiliary input not defined`); return entry; }, @@ -178,6 +176,7 @@ function createProgramState() { setAuxiliaryOutput(value: unknown, methodName: string) { methodCache.set(methodName, value); }, + getAuxiliaryOutput(methodName: string): unknown { let entry = methodCache.get(methodName); if (entry === undefined) @@ -845,7 +844,6 @@ function ZkProgram< publicInputAux ); - console.log('publicOutput after fromFieldAndAuxConsts', publicOutput); programState.resetAuxCache(); } else { // create public output when public input is pure From 1ee42364177b751d5f9499d66ab4ecbac993770f Mon Sep 17 00:00:00 2001 From: ymekuria Date: Mon, 21 Oct 2024 00:58:52 -0600 Subject: [PATCH 089/328] chore(CHANGELOG-v2.md): update changelog --- CHANGELOG-v2.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG-v2.md b/CHANGELOG-v2.md index 36efaddd12..adf2199c1a 100644 --- a/CHANGELOG-v2.md +++ b/CHANGELOG-v2.md @@ -30,11 +30,11 @@ Showing all changes since the last release (v.1.5.0) - Removed implicit version `Provable.equal(x, y)` where you didn't have to pass in the type -- `zkProgram` to support `auxiliaryOutput` +- `ZkProgram` to support `auxiliaryOutput` ### Added --`zkProgram` to support non-pure provable types as inputs and outputs https://github.com/o1-labs/o1js/pull/1828 +-`ZkProgram` to support non-pure provable types as inputs and outputs https://github.com/o1-labs/o1js/pull/1828 - New method `toCanonical()` in the `Provable` interface to protect against incompleteness of certain operations on malicious witness inputs https://github.com/o1-labs/o1js/pull/1759 - `divMod64()` division modulo 2^64 that returns the remainder and quotient of the operation From 80191e4a5a1a0a4ade8ddc7474aa913a42c5e838 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Mon, 21 Oct 2024 02:34:40 -0600 Subject: [PATCH 090/328] refactor(zkprogram.ts): remove unused function fromFieldConsts to clean up the code and improve maintainability --- src/lib/proof-system/zkprogram.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 962ce227b0..1828f8f4ca 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -1541,10 +1541,6 @@ function toFieldVars(type: ProvablePure, value: T) { return MlFieldArray.to(type.toFields(value)); } -function fromFieldConsts(type: any, fields: MlFieldConstArray) { - return type.fromFields(MlFieldConstArray.from(fields)); -} - function fromFieldAndAuxConsts( type: Provable, fields: MlFieldConstArray, From f23a636202f4c5fadd8b1e5883788e0680756459 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Mon, 21 Oct 2024 22:42:56 -0600 Subject: [PATCH 091/328] refactor(zkprogram.ts): rename auxInputCache to nonPureDataCache for clarity and consistency --- src/lib/proof-system/zkprogram.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 1828f8f4ca..d81a349724 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -161,14 +161,14 @@ const FeatureFlags = { }; function createProgramState() { - let auxInputCache: Map = new Map(); + let nonPureDataCache: Map = new Map(); let methodCache: Map = new Map(); return { setAuxilaryInput(value: any[]) { - auxInputCache.set('auxinput', value); + nonPureDataCache.set('auxinput', value); }, getAuxilaryInput: () => { - let entry = auxInputCache.get('auxinput'); + let entry = nonPureDataCache.get('auxinput'); if (entry === undefined) throw Error(`Auxiliary input not defined`); return entry; }, @@ -187,7 +187,7 @@ function createProgramState() { methodCache.delete(methodName); }, resetAuxCache() { - auxInputCache.delete('auxinput'); + nonPureDataCache.delete('auxinput'); }, }; } From 291f109f55b97e1a2d5299437c50342af11628e4 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Mon, 21 Oct 2024 22:47:22 -0600 Subject: [PATCH 092/328] refactor(zkprogram.ts): rename getAuxilaryInput to getNonPureInput for better clarity and consistency --- src/lib/proof-system/zkprogram.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index d81a349724..08d9ec61ea 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -167,7 +167,7 @@ function createProgramState() { setAuxilaryInput(value: any[]) { nonPureDataCache.set('auxinput', value); }, - getAuxilaryInput: () => { + getNonPureInput: () => { let entry = nonPureDataCache.get('auxinput'); if (entry === undefined) throw Error(`Auxiliary input not defined`); return entry; @@ -837,7 +837,7 @@ function ZkProgram< let publicOutput; let [publicOutputFields, proof] = MlPair.from(result); if (publicInputAuxExists) { - publicInputAux = programState.getAuxilaryInput(); + publicInputAux = programState.getNonPureInput(); publicOutput = fromFieldAndAuxConsts( publicOutputType, publicOutputFields, From b4f5dc7c99103796952570e45d1c07b0bd047257 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Mon, 21 Oct 2024 22:56:52 -0600 Subject: [PATCH 093/328] refactor(zkprogram.ts): rename setAuxilaryInput to setNonPureInput for clarity and consistency --- src/lib/proof-system/zkprogram.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 08d9ec61ea..aeb3afb8a7 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -164,7 +164,7 @@ function createProgramState() { let nonPureDataCache: Map = new Map(); let methodCache: Map = new Map(); return { - setAuxilaryInput(value: any[]) { + setNonPureInput(value: any[]) { nonPureDataCache.set('auxinput', value); }, getNonPureInput: () => { @@ -804,7 +804,7 @@ function ZkProgram< )); // store publicInput auxilary data in programState cache - programState.setAuxilaryInput(publicInputAux); + programState.setNonPureInput(publicInputAux); } else { publicInputFields = toFieldConsts(publicInputType, publicInput); } From 4c7e5fec2f0c65df912bee7f421d41daa847e96d Mon Sep 17 00:00:00 2001 From: ymekuria Date: Mon, 21 Oct 2024 23:10:19 -0600 Subject: [PATCH 094/328] refactor(zkprogram.ts): rename resetAuxCache function to resetNonPureDataCache for clarity and consistency with its purpose. --- src/lib/proof-system/zkprogram.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index aeb3afb8a7..ec21c0b495 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -186,7 +186,7 @@ function createProgramState() { reset(methodName: string) { methodCache.delete(methodName); }, - resetAuxCache() { + resetNonPureDataCache() { nonPureDataCache.delete('auxinput'); }, }; @@ -844,7 +844,7 @@ function ZkProgram< publicInputAux ); - programState.resetAuxCache(); + programState.resetNonPureDataCache(); } else { // create public output when public input is pure publicOutput = fromFieldAndAuxConsts( From 340bbd6432feb0691382790fd7f0d53bbb17d753 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Mon, 21 Oct 2024 23:21:40 -0600 Subject: [PATCH 095/328] feat(zkprogram.ts): update Zkprogram.proof PublicInputType from FlexibleProvablePure to FlexibleProvable --- src/lib/proof-system/zkprogram.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index ec21c0b495..b507906e77 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -1561,7 +1561,7 @@ function toFieldAndAuxConsts(type: Provable, value: T) { } ZkProgram.Proof = function < - PublicInputType extends FlexibleProvablePure, + PublicInputType extends FlexibleProvable, PublicOutputType extends FlexibleProvablePure >(program: { name: string; From 8f9c71c1562e7a666bb05851102e915503e1db71 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Mon, 21 Oct 2024 23:25:34 -0600 Subject: [PATCH 096/328] refactor(zkprogram.ts): update PublicOutputType constraint to match PublicInputType for consistency and clarity --- src/lib/proof-system/zkprogram.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index b507906e77..8e6c3afc38 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -1562,7 +1562,7 @@ function toFieldAndAuxConsts(type: Provable, value: T) { ZkProgram.Proof = function < PublicInputType extends FlexibleProvable, - PublicOutputType extends FlexibleProvablePure + PublicOutputType extends FlexibleProvable >(program: { name: string; publicInputType: PublicInputType; From 679e4998b979a9642c45a882210f4afb7272b128 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Tue, 22 Oct 2024 10:19:01 -0600 Subject: [PATCH 097/328] feat(zkprogram.ts): add setNonPureOutput function to store non-pure output data in cache for later use --- src/lib/proof-system/zkprogram.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 8e6c3afc38..7ca45dc64c 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -172,6 +172,9 @@ function createProgramState() { if (entry === undefined) throw Error(`Auxiliary input not defined`); return entry; }, + setNonPureOutput(value: any[]) { + nonPureDataCache.set('nonPureOutput', value); + }, setAuxiliaryOutput(value: unknown, methodName: string) { methodCache.set(methodName, value); From 4b192d469ee3002537c5d51f82d0911338baabe5 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Tue, 22 Oct 2024 10:24:13 -0600 Subject: [PATCH 098/328] feat(zkprogram.ts): store nonPureOutput in program state cache --- src/lib/proof-system/zkprogram.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 7ca45dc64c..a0fd192cb2 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -1319,6 +1319,8 @@ function picklesRuleFromFunction( result = (await func(input, ...finalArgs)) as any; } + let nonPureOutput = publicOutputType.toAuxiliary(result.publicOutput); + proofs.forEach(({ proofInstance, classReference }) => { if (!(proofInstance instanceof DynamicProof)) { return; From 595478a5fc635466d454bcdf157371274b647c40 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Tue, 22 Oct 2024 10:28:03 -0600 Subject: [PATCH 099/328] feat(zkprogram.ts): add getNonPureOutput method to programState cache --- src/lib/proof-system/zkprogram.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index a0fd192cb2..005230852d 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -175,7 +175,11 @@ function createProgramState() { setNonPureOutput(value: any[]) { nonPureDataCache.set('nonPureOutput', value); }, - + getNonPureOutput: () => { + let entry = nonPureDataCache.get('nonPureOutput'); + if (entry === undefined) throw Error(`Auxiliary output not defined`); + return entry; + }, setAuxiliaryOutput(value: unknown, methodName: string) { methodCache.set(methodName, value); }, From bbb52ea486a2cddf58900c6ac67b57bc3fc11f43 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Tue, 22 Oct 2024 23:17:51 -0600 Subject: [PATCH 100/328] feat(zkprogram.ts): add key parameter to resetNonPureDataCache method for flexibility --- src/lib/proof-system/zkprogram.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 005230852d..ceff4013ae 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -180,6 +180,7 @@ function createProgramState() { if (entry === undefined) throw Error(`Auxiliary output not defined`); return entry; }, + setAuxiliaryOutput(value: unknown, methodName: string) { methodCache.set(methodName, value); }, @@ -193,8 +194,8 @@ function createProgramState() { reset(methodName: string) { methodCache.delete(methodName); }, - resetNonPureDataCache() { - nonPureDataCache.delete('auxinput'); + resetNonPureDataCache(key: string) { + nonPureDataCache.delete(key); }, }; } @@ -845,6 +846,7 @@ function ZkProgram< let [publicOutputFields, proof] = MlPair.from(result); if (publicInputAuxExists) { publicInputAux = programState.getNonPureInput(); + publicOutput = fromFieldAndAuxConsts( publicOutputType, publicOutputFields, From 87f1bf957f25d281ad8990acff58a4d0c90e26a9 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Tue, 22 Oct 2024 23:49:48 -0600 Subject: [PATCH 101/328] feat(zkprogram.ts): update method call to reset nonPureDataCache with 'nonPureInput' key for accuracy --- src/lib/proof-system/zkprogram.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index ceff4013ae..d75b7d26c6 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -165,10 +165,10 @@ function createProgramState() { let methodCache: Map = new Map(); return { setNonPureInput(value: any[]) { - nonPureDataCache.set('auxinput', value); + nonPureDataCache.set('nonPureInput', value); }, getNonPureInput: () => { - let entry = nonPureDataCache.get('auxinput'); + let entry = nonPureDataCache.get('nonPureInput'); if (entry === undefined) throw Error(`Auxiliary input not defined`); return entry; }, @@ -853,7 +853,7 @@ function ZkProgram< publicInputAux ); - programState.resetNonPureDataCache(); + programState.resetNonPureDataCache('nonPureInput'); } else { // create public output when public input is pure publicOutput = fromFieldAndAuxConsts( From 5fc295c9de7da8427758d7a48871bfb7f22791b0 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 23 Oct 2024 00:06:01 -0600 Subject: [PATCH 102/328] feat(program-with-non-pure-input.ts): update input struct label property in zkprogram example --- src/examples/zkprogram/program-with-non-pure-input.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/examples/zkprogram/program-with-non-pure-input.ts b/src/examples/zkprogram/program-with-non-pure-input.ts index 0a1224113c..4013a29dbc 100644 --- a/src/examples/zkprogram/program-with-non-pure-input.ts +++ b/src/examples/zkprogram/program-with-non-pure-input.ts @@ -14,6 +14,8 @@ let MyProgram = ZkProgram({ baseCase: { privateInputs: [], async method(input: MyStruct) { + //update input in circuit + input.label = 'inCircuit'; return { publicOutput: input, }; @@ -22,13 +24,15 @@ let MyProgram = ZkProgram({ }, }); +// + console.log('compiling MyProgram...'); await MyProgram.compile(); console.log('compile done'); let input = new MyStruct({ label: 'input', value: Field(5) }); + let result = await MyProgram.baseCase(input); let ok = await MyProgram.verify(result.proof); -console.log('ok', ok); assert(ok, 'proof not valid!'); From 29fc2d8b10f1ed87be814d1355e9bd27dd954272 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 23 Oct 2024 00:29:12 -0600 Subject: [PATCH 103/328] feat(zkprogram.ts): add non pure output to program state cache --- src/lib/proof-system/zkprogram.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index d75b7d26c6..06d7f61d78 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -1326,6 +1326,7 @@ function picklesRuleFromFunction( } let nonPureOutput = publicOutputType.toAuxiliary(result.publicOutput); + state?.setNonPureOutput(nonPureOutput); proofs.forEach(({ proofInstance, classReference }) => { if (!(proofInstance instanceof DynamicProof)) { From a218e97cfdc97919aa4bacc671c13f41ece131ec Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 23 Oct 2024 01:12:04 -0600 Subject: [PATCH 104/328] feat(zkprogram.ts): rename publicInputAuxExists variable to nonPureInputExists for clarity --- src/lib/proof-system/zkprogram.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 06d7f61d78..1f7037b7ae 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -800,11 +800,11 @@ function ZkProgram< ); } - let publicInputAuxExists = + let nonPureInputExists = publicInputType.toAuxiliary(publicInput).length !== 0; let publicInputFields, publicInputAux; - if (publicInputAuxExists) { + if (nonPureInputExists) { // serialize publicInput into pure provable field elements and auxilary data ({ publicInputFields, publicInputAux } = toFieldAndAuxConsts( publicInputType, @@ -844,7 +844,7 @@ function ZkProgram< let publicOutput; let [publicOutputFields, proof] = MlPair.from(result); - if (publicInputAuxExists) { + if (nonPureInputExists) { publicInputAux = programState.getNonPureInput(); publicOutput = fromFieldAndAuxConsts( @@ -855,7 +855,6 @@ function ZkProgram< programState.resetNonPureDataCache('nonPureInput'); } else { - // create public output when public input is pure publicOutput = fromFieldAndAuxConsts( publicOutputType, publicOutputFields From 333efcff3c6a91e8689a067e966d1c598cd9f5da Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 23 Oct 2024 01:32:44 -0600 Subject: [PATCH 105/328] feat(zkprogram.ts): set non-pure output in cash only if it exists to avoid unnecessary operations --- src/lib/proof-system/zkprogram.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 1f7037b7ae..76a31a67e3 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -845,7 +845,8 @@ function ZkProgram< let publicOutput; let [publicOutputFields, proof] = MlPair.from(result); if (nonPureInputExists) { - publicInputAux = programState.getNonPureInput(); + publicInputAux = programState.getNonPureOutput(); + console.log('result of get utput', publicInputAux); publicOutput = fromFieldAndAuxConsts( publicOutputType, @@ -1325,7 +1326,11 @@ function picklesRuleFromFunction( } let nonPureOutput = publicOutputType.toAuxiliary(result.publicOutput); - state?.setNonPureOutput(nonPureOutput); + let nonPureOutputExists = nonPureOutput.length !== 0; + + if (state !== undefined && nonPureOutputExists) { + state?.setNonPureOutput(nonPureOutput); + } proofs.forEach(({ proofInstance, classReference }) => { if (!(proofInstance instanceof DynamicProof)) { From b9c131ff8afc419338b3ed1a0cd3c14d13830b9a Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 23 Oct 2024 02:10:32 -0600 Subject: [PATCH 106/328] feat(zkprogram.ts):recompose publicOutput from nonPureOutput and outputFields --- src/lib/proof-system/zkprogram.ts | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 76a31a67e3..3fb4b1526a 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -802,7 +802,7 @@ function ZkProgram< let nonPureInputExists = publicInputType.toAuxiliary(publicInput).length !== 0; - + console.log('nonPure Input Exists', nonPureInputExists); let publicInputFields, publicInputAux; if (nonPureInputExists) { // serialize publicInput into pure provable field elements and auxilary data @@ -845,16 +845,21 @@ function ZkProgram< let publicOutput; let [publicOutputFields, proof] = MlPair.from(result); if (nonPureInputExists) { - publicInputAux = programState.getNonPureOutput(); - console.log('result of get utput', publicInputAux); + let nonPureOutput = programState.getNonPureOutput(); + let nonPureOutputExists = nonPureOutput.length !== 0; + + let nonPureData = nonPureOutputExists + ? nonPureOutput + : programState.getNonPureInput(); publicOutput = fromFieldAndAuxConsts( publicOutputType, publicOutputFields, - publicInputAux + nonPureData ); programState.resetNonPureDataCache('nonPureInput'); + programState.resetNonPureDataCache('nonPureOutPut'); } else { publicOutput = fromFieldAndAuxConsts( publicOutputType, @@ -1326,10 +1331,10 @@ function picklesRuleFromFunction( } let nonPureOutput = publicOutputType.toAuxiliary(result.publicOutput); - let nonPureOutputExists = nonPureOutput.length !== 0; + let nonPureOutputExists = nonPureOutput[0].length !== 0; if (state !== undefined && nonPureOutputExists) { - state?.setNonPureOutput(nonPureOutput); + state.setNonPureOutput(nonPureOutput); } proofs.forEach(({ proofInstance, classReference }) => { From 5e5b8423b5a7ff5e1005551cc2aaea182b9f2a9c Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 23 Oct 2024 02:13:27 -0600 Subject: [PATCH 107/328] feat(program-with-non-pure-input.ts): add assertion to check struct label was updated --- src/examples/zkprogram/program-with-non-pure-input.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/examples/zkprogram/program-with-non-pure-input.ts b/src/examples/zkprogram/program-with-non-pure-input.ts index 4013a29dbc..123ec7603a 100644 --- a/src/examples/zkprogram/program-with-non-pure-input.ts +++ b/src/examples/zkprogram/program-with-non-pure-input.ts @@ -32,7 +32,8 @@ console.log('compile done'); let input = new MyStruct({ label: 'input', value: Field(5) }); -let result = await MyProgram.baseCase(input); -let ok = await MyProgram.verify(result.proof); +let { proof } = await MyProgram.baseCase(input); +let ok = await MyProgram.verify(proof); assert(ok, 'proof not valid!'); +assert(proof.publicOutput.label === 'inCircuit'); From 138045fa44bb60a50cc8a493d9265c4abd76658c Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 23 Oct 2024 19:33:32 -0600 Subject: [PATCH 108/328] feat(zkprogram.ts): add `getNonPureUpdate` function to check if non pure auxilary data was updated in-circuit --- src/lib/proof-system/zkprogram.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 3fb4b1526a..dceaae8d89 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -1802,3 +1802,19 @@ type UnwrapPromise

= P extends Promise ? T : never; type Get = T extends { [K in Key]: infer Value } ? Value : undefined; + +function getNonPureUpdate(nonPureInput: any[], nonPureOutput: any[]): any[] { + var result = []; + for (var i = 0; i < nonPureOutput.length; i++) { + if (Array.isArray(nonPureOutput[i])) { + result[i] = getNonPureUpdate(nonPureInput[i], nonPureOutput[i]); + } else { + if (nonPureOutput[i] !== '') { + result[i] = nonPureOutput[i]; + } else { + result[i] = nonPureInput[i]; + } + } + } + return result; +} From 82676777dd9f4ef71b97af015b7e6f9f2eaafe37 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 23 Oct 2024 19:49:56 -0600 Subject: [PATCH 109/328] feat(zkprogram.ts): add check for result publicOutput before adding aux data to cache --- src/lib/proof-system/zkprogram.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index dceaae8d89..99fef08ff6 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -1330,11 +1330,14 @@ function picklesRuleFromFunction( result = (await func(input, ...finalArgs)) as any; } - let nonPureOutput = publicOutputType.toAuxiliary(result.publicOutput); - let nonPureOutputExists = nonPureOutput[0].length !== 0; + if (result.publicOutput) { + // store the nonPure auxiliary data in program state cache if it exists + let nonPureOutput = publicOutputType.toAuxiliary(result.publicOutput); + let nonPureOutputExists = nonPureOutput.length !== 0; - if (state !== undefined && nonPureOutputExists) { - state.setNonPureOutput(nonPureOutput); + if (state !== undefined && nonPureOutputExists) { + state.setNonPureOutput(nonPureOutput); + } } proofs.forEach(({ proofInstance, classReference }) => { From fbc199daad0aa091e0279a795e9c1158eb2c9bcd Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 23 Oct 2024 20:01:40 -0600 Subject: [PATCH 110/328] feat(zkprogram.ts): deserialize proof public output with updates to aux data made in circuit --- src/lib/proof-system/zkprogram.ts | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 99fef08ff6..d094e4b2d7 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -846,20 +846,19 @@ function ZkProgram< let [publicOutputFields, proof] = MlPair.from(result); if (nonPureInputExists) { let nonPureOutput = programState.getNonPureOutput(); - let nonPureOutputExists = nonPureOutput.length !== 0; - - let nonPureData = nonPureOutputExists - ? nonPureOutput - : programState.getNonPureInput(); + let nonPureInput = programState.getNonPureInput(); + // get updates that were made to non-pure auxiliary data in-circuit + let nonPureUpdate = getNonPureUpdate(nonPureInput, nonPureOutput); + console.log('nonPureUpdate', nonPureUpdate); publicOutput = fromFieldAndAuxConsts( publicOutputType, publicOutputFields, - nonPureData + nonPureUpdate ); programState.resetNonPureDataCache('nonPureInput'); - programState.resetNonPureDataCache('nonPureOutPut'); + programState.resetNonPureDataCache('nonPureOutput'); } else { publicOutput = fromFieldAndAuxConsts( publicOutputType, From 4f377178404b85c2f0ae4f33d9907a1901303e13 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Tue, 29 Oct 2024 17:17:57 -0700 Subject: [PATCH 111/328] feat(provable-context.ts): add auxInputData field to SnarkContext type for additional input data support --- src/lib/provable/core/provable-context.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib/provable/core/provable-context.ts b/src/lib/provable/core/provable-context.ts index a697c5d00d..ee44ab9c5e 100644 --- a/src/lib/provable/core/provable-context.ts +++ b/src/lib/provable/core/provable-context.ts @@ -40,6 +40,7 @@ type SnarkContext = { inCheckedComputation?: boolean; inAnalyze?: boolean; inWitnessBlock?: boolean; + auxInputData?: any[]; }; let snarkContext = Context.create({ default: {} }); From dddffadaaceadb5ce7123bb15a26bc7018346a4b Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 30 Oct 2024 14:20:28 -0700 Subject: [PATCH 112/328] feat(zkprogram.ts): add auxInputData to snarkContext --- src/lib/proof-system/zkprogram.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index d094e4b2d7..f235c03375 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -821,7 +821,11 @@ function ZkProgram< getPreviousProofsForProver(args, methodIntfs[i]) ); - let id = snarkContext.enter({ witnesses: args, inProver: true }); + let id = snarkContext.enter({ + witnesses: args, + inProver: true, + auxInputData: publicInputAux, + }); let result: UnwrapPromise>; try { result = await picklesProver(publicInputFields, previousProofs); @@ -848,7 +852,7 @@ function ZkProgram< let nonPureOutput = programState.getNonPureOutput(); let nonPureInput = programState.getNonPureInput(); - // get updates that were made to non-pure auxiliary data in-circuit + // get update made to non-pure auxiliary data in circuit let nonPureUpdate = getNonPureUpdate(nonPureInput, nonPureOutput); console.log('nonPureUpdate', nonPureUpdate); publicOutput = fromFieldAndAuxConsts( From 3f6584583a4b3dc4daa15d9f493d09660105768a Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 30 Oct 2024 14:25:10 -0700 Subject: [PATCH 113/328] feat(zkprogram.ts): get auxInputData from snarkContext in `picklesRuleFromFunction` --- src/lib/proof-system/zkprogram.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index f235c03375..8d26676c1f 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -826,6 +826,7 @@ function ZkProgram< inProver: true, auxInputData: publicInputAux, }); + let result: UnwrapPromise>; try { result = await picklesProver(publicInputFields, previousProofs); @@ -1283,7 +1284,11 @@ function picklesRuleFromFunction( async function main( publicInput: MlFieldArray ): ReturnType { - let { witnesses: argsWithoutPublicInput, inProver } = snarkContext.get(); + let { + witnesses: argsWithoutPublicInput, + inProver, + auxInputData, + } = snarkContext.get(); assert(!(inProver && argsWithoutPublicInput === undefined)); let finalArgs = []; let proofs: { From cd7bb4204fca5847e6a0f9b05a48428b04ba5e21 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 30 Oct 2024 14:44:20 -0700 Subject: [PATCH 114/328] feat(zkprogram.ts): update fromFieldVars function signature to include auxData parameter for additional flexibility and reusability --- src/lib/proof-system/zkprogram.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 8d26676c1f..8a5a82f818 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -821,6 +821,7 @@ function ZkProgram< getPreviousProofsForProver(args, methodIntfs[i]) ); + console.log('auxdata before entering snarkContext ', publicInputAux); let id = snarkContext.enter({ witnesses: args, inProver: true, @@ -1565,8 +1566,12 @@ function getMaxProofsVerified(methodIntfs: MethodInterface[]) { ) as any as 0 | 1 | 2; } -function fromFieldVars(type: Provable, fields: MlFieldArray) { - return type.fromFields(MlFieldArray.from(fields), []); +function fromFieldVars( + type: Provable, + fields: MlFieldArray, + auxData: any[] = [] +) { + return type.fromFields(MlFieldArray.from(fields), auxData); } function toFieldVars(type: ProvablePure, value: T) { From 80438a9d8b84e32f2b635145d7b272a490d6096a Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 30 Oct 2024 14:47:32 -0700 Subject: [PATCH 115/328] feat(zkprogram.ts): deserilze input with auxInputData from snarkContext --- src/lib/proof-system/zkprogram.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 8a5a82f818..89bcc1b551 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -1335,10 +1335,12 @@ function picklesRuleFromFunction( if (publicInputType === Undefined || publicInputType === Void) { result = (await func(...finalArgs)) as any; } else { - let input = fromFieldVars(publicInputType, publicInput); + console.log('auxData before input', auxInputData); + let input = fromFieldVars(publicInputType, publicInput, auxInputData); result = (await func(input, ...finalArgs)) as any; } + console.log('result input', result); if (result.publicOutput) { // store the nonPure auxiliary data in program state cache if it exists let nonPureOutput = publicOutputType.toAuxiliary(result.publicOutput); From 05ac4feed6a44efcce964710eab5aa8dfcbac534 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 30 Oct 2024 14:53:59 -0700 Subject: [PATCH 116/328] feat(zkprogram.ts): deserialize publicOutput with nonPureOutput --- src/lib/proof-system/zkprogram.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 89bcc1b551..6fa032171b 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -860,7 +860,7 @@ function ZkProgram< publicOutput = fromFieldAndAuxConsts( publicOutputType, publicOutputFields, - nonPureUpdate + nonPureOutput ); programState.resetNonPureDataCache('nonPureInput'); From a143585512635afb329130ad305e07d1b5b341cf Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 30 Oct 2024 15:07:36 -0700 Subject: [PATCH 117/328] refactor(zkprogram.ts): remove unused code --- src/examples/zkprogram/program-with-non-pure-input.ts | 5 ++++- src/lib/proof-system/zkprogram.ts | 5 ----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/examples/zkprogram/program-with-non-pure-input.ts b/src/examples/zkprogram/program-with-non-pure-input.ts index 123ec7603a..4b34ea3132 100644 --- a/src/examples/zkprogram/program-with-non-pure-input.ts +++ b/src/examples/zkprogram/program-with-non-pure-input.ts @@ -2,6 +2,7 @@ import { Field, Provable, Struct, ZkProgram, assert } from 'o1js'; class MyStruct extends Struct({ label: String, + description: String, value: Field, }) {} @@ -35,5 +36,7 @@ let input = new MyStruct({ label: 'input', value: Field(5) }); let { proof } = await MyProgram.baseCase(input); let ok = await MyProgram.verify(proof); +console.log('proof', proof); + assert(ok, 'proof not valid!'); -assert(proof.publicOutput.label === 'inCircuit'); +// assert(proof.publicOutput.label === 'inCircuit'); diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 6fa032171b..30d9e7909b 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -852,18 +852,13 @@ function ZkProgram< let [publicOutputFields, proof] = MlPair.from(result); if (nonPureInputExists) { let nonPureOutput = programState.getNonPureOutput(); - let nonPureInput = programState.getNonPureInput(); - // get update made to non-pure auxiliary data in circuit - let nonPureUpdate = getNonPureUpdate(nonPureInput, nonPureOutput); - console.log('nonPureUpdate', nonPureUpdate); publicOutput = fromFieldAndAuxConsts( publicOutputType, publicOutputFields, nonPureOutput ); - programState.resetNonPureDataCache('nonPureInput'); programState.resetNonPureDataCache('nonPureOutput'); } else { publicOutput = fromFieldAndAuxConsts( From 04326e851d60e3416109cc35b73ae11857724ede Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 30 Oct 2024 15:08:42 -0700 Subject: [PATCH 118/328] refactor(zkprogram.ts): remove unused getNonPureUpdate function to improve code readability and maintainability --- src/lib/proof-system/zkprogram.ts | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 30d9e7909b..5ff12f57e8 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -1815,19 +1815,3 @@ type UnwrapPromise

= P extends Promise ? T : never; type Get = T extends { [K in Key]: infer Value } ? Value : undefined; - -function getNonPureUpdate(nonPureInput: any[], nonPureOutput: any[]): any[] { - var result = []; - for (var i = 0; i < nonPureOutput.length; i++) { - if (Array.isArray(nonPureOutput[i])) { - result[i] = getNonPureUpdate(nonPureInput[i], nonPureOutput[i]); - } else { - if (nonPureOutput[i] !== '') { - result[i] = nonPureOutput[i]; - } else { - result[i] = nonPureInput[i]; - } - } - } - return result; -} From b6c146e0a8ec4dfc31499aa596a0d1ecd2d06c93 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 30 Oct 2024 15:12:49 -0700 Subject: [PATCH 119/328] refactor(zkprogram.ts): rename to fromFieldConsts --- src/lib/proof-system/zkprogram.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 5ff12f57e8..698092075b 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -853,7 +853,7 @@ function ZkProgram< if (nonPureInputExists) { let nonPureOutput = programState.getNonPureOutput(); - publicOutput = fromFieldAndAuxConsts( + publicOutput = fromFieldConsts( publicOutputType, publicOutputFields, nonPureOutput @@ -861,10 +861,7 @@ function ZkProgram< programState.resetNonPureDataCache('nonPureOutput'); } else { - publicOutput = fromFieldAndAuxConsts( - publicOutputType, - publicOutputFields - ); + publicOutput = fromFieldConsts(publicOutputType, publicOutputFields); } return { @@ -1575,7 +1572,7 @@ function toFieldVars(type: ProvablePure, value: T) { return MlFieldArray.to(type.toFields(value)); } -function fromFieldAndAuxConsts( +function fromFieldConsts( type: Provable, fields: MlFieldConstArray, aux: any[] = [] From 52699f0cea62c6b0a08e4a94010dd559e891a38b Mon Sep 17 00:00:00 2001 From: ymekuria Date: Tue, 5 Nov 2024 10:39:32 +0900 Subject: [PATCH 120/328] feat(program-with-non-pure-input.ts): remove unused 'description' field from MyStruct and add assertion to check for 'label' value in proof.publicOutput --- src/examples/zkprogram/program-with-non-pure-input.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/examples/zkprogram/program-with-non-pure-input.ts b/src/examples/zkprogram/program-with-non-pure-input.ts index 4b34ea3132..c5d87017f3 100644 --- a/src/examples/zkprogram/program-with-non-pure-input.ts +++ b/src/examples/zkprogram/program-with-non-pure-input.ts @@ -2,7 +2,6 @@ import { Field, Provable, Struct, ZkProgram, assert } from 'o1js'; class MyStruct extends Struct({ label: String, - description: String, value: Field, }) {} @@ -39,4 +38,4 @@ let ok = await MyProgram.verify(proof); console.log('proof', proof); assert(ok, 'proof not valid!'); -// assert(proof.publicOutput.label === 'inCircuit'); +assert(proof.publicOutput.label === 'inCircuit'); From f67d05478be2de423d3a761143b942b76a060e18 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Tue, 5 Nov 2024 10:46:52 +0900 Subject: [PATCH 121/328] result(zkprogram.ts): refactor publicOutput result conditional check to use optional chaining for improved readability and null safety --- src/lib/proof-system/zkprogram.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 698092075b..7fa1d44f57 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -1333,7 +1333,7 @@ function picklesRuleFromFunction( } console.log('result input', result); - if (result.publicOutput) { + if (result?.publicOutput) { // store the nonPure auxiliary data in program state cache if it exists let nonPureOutput = publicOutputType.toAuxiliary(result.publicOutput); let nonPureOutputExists = nonPureOutput.length !== 0; From 24ce22c94b84d3f87f12a1a2ba8aba8b03c236bf Mon Sep 17 00:00:00 2001 From: ymekuria Date: Tue, 5 Nov 2024 11:02:30 +0900 Subject: [PATCH 122/328] refactor(program-with-non-pure-input.ts): remove unnecessary console.log statement for 'proof' variable --- src/examples/zkprogram/program-with-non-pure-input.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/examples/zkprogram/program-with-non-pure-input.ts b/src/examples/zkprogram/program-with-non-pure-input.ts index c5d87017f3..123ec7603a 100644 --- a/src/examples/zkprogram/program-with-non-pure-input.ts +++ b/src/examples/zkprogram/program-with-non-pure-input.ts @@ -35,7 +35,5 @@ let input = new MyStruct({ label: 'input', value: Field(5) }); let { proof } = await MyProgram.baseCase(input); let ok = await MyProgram.verify(proof); -console.log('proof', proof); - assert(ok, 'proof not valid!'); assert(proof.publicOutput.label === 'inCircuit'); From 02b8b787eecadbb2c0a4f01102030e4b79b33c5c Mon Sep 17 00:00:00 2001 From: ymekuria Date: Tue, 12 Nov 2024 00:16:45 +0700 Subject: [PATCH 123/328] refactor(zkprogram.ts): change arrow function syntax for consistency --- src/lib/proof-system/zkprogram.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 7fa1d44f57..fb3a718188 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -167,7 +167,7 @@ function createProgramState() { setNonPureInput(value: any[]) { nonPureDataCache.set('nonPureInput', value); }, - getNonPureInput: () => { + getNonPureInput() { let entry = nonPureDataCache.get('nonPureInput'); if (entry === undefined) throw Error(`Auxiliary input not defined`); return entry; @@ -175,7 +175,7 @@ function createProgramState() { setNonPureOutput(value: any[]) { nonPureDataCache.set('nonPureOutput', value); }, - getNonPureOutput: () => { + getNonPureOutput(): any { let entry = nonPureDataCache.get('nonPureOutput'); if (entry === undefined) throw Error(`Auxiliary output not defined`); return entry; From ff9852be3df1faa5c83de3845919fb42d6b79942 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Tue, 12 Nov 2024 00:25:33 +0700 Subject: [PATCH 124/328] refactor(zkprogram.ts): merge nonPureDataCache with methodCache to clean up code and improve readability --- src/lib/proof-system/zkprogram.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index fb3a718188..0d3c546b0b 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -161,7 +161,6 @@ const FeatureFlags = { }; function createProgramState() { - let nonPureDataCache: Map = new Map(); let methodCache: Map = new Map(); return { setNonPureInput(value: any[]) { From 5687495118ca125e5f4f57b75a20c8170fc6572f Mon Sep 17 00:00:00 2001 From: ymekuria Date: Tue, 12 Nov 2024 00:32:22 +0700 Subject: [PATCH 125/328] feat(zkprogram.ts): use methodCache to set non pure inputs and outputs --- src/lib/proof-system/zkprogram.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 0d3c546b0b..d371ec0e92 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -164,7 +164,7 @@ function createProgramState() { let methodCache: Map = new Map(); return { setNonPureInput(value: any[]) { - nonPureDataCache.set('nonPureInput', value); + methodCache.set('nonPureInput', value); }, getNonPureInput() { let entry = nonPureDataCache.get('nonPureInput'); @@ -172,7 +172,7 @@ function createProgramState() { return entry; }, setNonPureOutput(value: any[]) { - nonPureDataCache.set('nonPureOutput', value); + methodCache.set('nonPureOutput', value); }, getNonPureOutput(): any { let entry = nonPureDataCache.get('nonPureOutput'); From 35420b1e372b1260f8e00bf1803a2f5cc016e64a Mon Sep 17 00:00:00 2001 From: ymekuria Date: Tue, 12 Nov 2024 00:36:07 +0700 Subject: [PATCH 126/328] feat(zkprogram.ts): use methodCache to get non pure inputs and outputs --- src/lib/proof-system/zkprogram.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index d371ec0e92..c89dae7666 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -167,7 +167,7 @@ function createProgramState() { methodCache.set('nonPureInput', value); }, getNonPureInput() { - let entry = nonPureDataCache.get('nonPureInput'); + let entry = methodCache.get('nonPureInput'); if (entry === undefined) throw Error(`Auxiliary input not defined`); return entry; }, @@ -175,7 +175,7 @@ function createProgramState() { methodCache.set('nonPureOutput', value); }, getNonPureOutput(): any { - let entry = nonPureDataCache.get('nonPureOutput'); + let entry = methodCache.get('nonPureOutput'); if (entry === undefined) throw Error(`Auxiliary output not defined`); return entry; }, @@ -194,7 +194,7 @@ function createProgramState() { methodCache.delete(methodName); }, resetNonPureDataCache(key: string) { - nonPureDataCache.delete(key); + methodCache.delete(key); }, }; } From a03f1f57718b7a8003ea823ecded158b1eebdd7b Mon Sep 17 00:00:00 2001 From: ymekuria Date: Tue, 12 Nov 2024 00:39:43 +0700 Subject: [PATCH 127/328] refactor(zkprogram.ts): change return type of getNonPureInput and getNonPureOutput to improve code clarity and type safety --- src/lib/proof-system/zkprogram.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index c89dae7666..30927b3fd2 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -166,7 +166,7 @@ function createProgramState() { setNonPureInput(value: any[]) { methodCache.set('nonPureInput', value); }, - getNonPureInput() { + getNonPureInput(): any[] { let entry = methodCache.get('nonPureInput'); if (entry === undefined) throw Error(`Auxiliary input not defined`); return entry; @@ -174,7 +174,7 @@ function createProgramState() { setNonPureOutput(value: any[]) { methodCache.set('nonPureOutput', value); }, - getNonPureOutput(): any { + getNonPureOutput(): any[] { let entry = methodCache.get('nonPureOutput'); if (entry === undefined) throw Error(`Auxiliary output not defined`); return entry; From 0303637ed6ffbbdd6993cc319a64477da7126a95 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Tue, 12 Nov 2024 00:52:08 +0700 Subject: [PATCH 128/328] refactor(zkprogram.ts): improve error message for undefined non-pure input and output variables to be more descriptive and accurate --- src/lib/proof-system/zkprogram.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 30927b3fd2..c52945bc9a 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -168,16 +168,16 @@ function createProgramState() { }, getNonPureInput(): any[] { let entry = methodCache.get('nonPureInput'); - if (entry === undefined) throw Error(`Auxiliary input not defined`); - return entry; + if (entry === undefined) throw Error(`Non-pure input not defined`); + return entry as any[]; }, setNonPureOutput(value: any[]) { methodCache.set('nonPureOutput', value); }, getNonPureOutput(): any[] { let entry = methodCache.get('nonPureOutput'); - if (entry === undefined) throw Error(`Auxiliary output not defined`); - return entry; + if (entry === undefined) throw Error(`Non-pure output not defined`); + return entry as any[]; }, setAuxiliaryOutput(value: unknown, methodName: string) { From be54738eea31f9747635c4eb0917b77d49039116 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Tue, 12 Nov 2024 00:59:22 +0700 Subject: [PATCH 129/328] refactor(zkprogram.ts): merge programState reset methods --- src/lib/proof-system/zkprogram.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index c52945bc9a..ed99ecfb8f 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -190,10 +190,7 @@ function createProgramState() { throw Error(`Auxiliary value for method ${methodName} not defined`); return entry; }, - reset(methodName: string) { - methodCache.delete(methodName); - }, - resetNonPureDataCache(key: string) { + reset(key: string) { methodCache.delete(key); }, }; @@ -858,7 +855,7 @@ function ZkProgram< nonPureOutput ); - programState.resetNonPureDataCache('nonPureOutput'); + programState.reset('nonPureOutput'); } else { publicOutput = fromFieldConsts(publicOutputType, publicOutputFields); } From 24b1bd72e0d7d2de571bcb3117a54dc4c88a3c50 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 13 Nov 2024 12:59:31 +0700 Subject: [PATCH 130/328] chore(CHANGELOG): delete CHANGELOG-v2.md file as it is no longer needed --- CHANGELOG-v2.md | 43 ------------------------------------------- CHANGELOG.md | 2 ++ 2 files changed, 2 insertions(+), 43 deletions(-) delete mode 100644 CHANGELOG-v2.md diff --git a/CHANGELOG-v2.md b/CHANGELOG-v2.md deleted file mode 100644 index bbf2309efb..0000000000 --- a/CHANGELOG-v2.md +++ /dev/null @@ -1,43 +0,0 @@ -# Changelog - -All notable changes to this project are documented in this file. - -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). -This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - - - - - -Showing all changes since the last release (v.1.5.0) ---> - -## [Unreleased](https://github.com/o1-labs/o1js/compare/1c736add...v2) - 2024-07-12 - -### Breaking Changes - -- The `divMod32()` gadget was modified to accept `nBits` instead of `quotientBits`, and assert it is in the range [0, 2\*\*255) to address an issue previoulsy where the bound on `quotientBits` was too low https://github.com/o1-labs/o1js/pull/1763. - -- `Provable.equal()` now turns both types into canonical form before comparing them https://github.com/o1-labs/o1js/pull/1759 - - - Removed implicit version `Provable.equal(x, y)` where you didn't have to pass in the type - -- `ZkProgram` to support `auxiliaryOutput` - -### Added - --`ZkProgram` to support non-pure provable types as inputs and outputs https://github.com/o1-labs/o1js/pull/1828 - -- New method `toCanonical()` in the `Provable` interface to protect against incompleteness of certain operations on malicious witness inputs https://github.com/o1-labs/o1js/pull/1759 -- `divMod64()` division modulo 2^64 that returns the remainder and quotient of the operation -- `addMod64()` addition modulo 2^64 -- Bitwise OR via `{UInt32, UInt64}.or()` -- **BLAKE2B hash function** gadget [#1285](https://github.com/o1-labs/o1js/pull/1285) diff --git a/CHANGELOG.md b/CHANGELOG.md index b0cd869cc7..400815b4c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,8 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ### Added +-`ZkProgram` to support non-pure provable types as inputs and outputs https://github.com/o1-labs/o1js/pull/1828 + - Support secp256r1 in elliptic curve and ECDSA gadgets https://github.com/o1-labs/o1js/pull/1885 ### Fixed From 4aa4b99ad830db2870789480f9b26f05ba0373be Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 13 Nov 2024 13:03:00 +0700 Subject: [PATCH 131/328] feat(proof.ts): update proof.ts publicInput and output file to useFlexibleProvablePure to FlexibleProvable --- src/lib/proof-system/proof.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib/proof-system/proof.ts b/src/lib/proof-system/proof.ts index 9111482cf9..f19402fc8d 100644 --- a/src/lib/proof-system/proof.ts +++ b/src/lib/proof-system/proof.ts @@ -2,7 +2,7 @@ import { initializeBindings, withThreadPool } from '../../snarky.js'; import { Pickles } from '../../snarky.js'; import { Field, Bool } from '../provable/wrapped.js'; import type { - FlexibleProvablePure, + FlexibleProvable, InferProvable, } from '../provable/types/struct.js'; import { FeatureFlags } from './feature-flags.js'; @@ -22,8 +22,8 @@ export { dummyProof, extractProofs, extractProofTypes, type ProofValue }; type MaxProofs = 0 | 1 | 2; class ProofBase { - static publicInputType: FlexibleProvablePure = undefined as any; - static publicOutputType: FlexibleProvablePure = undefined as any; + static publicInputType: FlexibleProvable = undefined as any; + static publicOutputType: FlexibleProvable = undefined as any; static tag: () => { name: string } = () => { throw Error( `You cannot use the \`Proof\` class directly. Instead, define a subclass:\n` + From cad292fcbcc8e68d408036bdce50bf1c43403c70 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 13 Nov 2024 13:07:46 +0700 Subject: [PATCH 132/328] feature(zkprogram.ts): updated proof public input and output type to FlexibleProvable --- src/lib/proof-system/zkprogram.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index f0e3437a6e..8f818f139a 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -3,7 +3,7 @@ import { Snarky, initializeBindings, withThreadPool } from '../../snarky.js'; import { Pickles, Gate } from '../../snarky.js'; import { Field } from '../provable/wrapped.js'; import { - FlexibleProvablePure, + FlexibleProvable, InferProvable, ProvablePureExtended, Struct, From a4725e3d711d1a1f85abfa2a12fcad906f19e75a Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 13 Nov 2024 22:46:17 +0700 Subject: [PATCH 133/328] chore(bindings): update subproject commit reference to acc5a7c56645ea46f58e698bca75a011407d45b0 --- src/bindings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bindings b/src/bindings index 59eb4c0c3c..acc5a7c566 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit 59eb4c0c3c126819a88624e0445ea31f89c5850a +Subproject commit acc5a7c56645ea46f58e698bca75a011407d45b0 From 7948c23dcf1611522365b130b6c68200da2cd0ec Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 13 Nov 2024 23:25:34 +0700 Subject: [PATCH 134/328] style(program-with-non-pure-input.ts): update input label from 'inCircuit' to 'in-circuit' for consistency and readability --- src/examples/zkprogram/program-with-non-pure-input.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/examples/zkprogram/program-with-non-pure-input.ts b/src/examples/zkprogram/program-with-non-pure-input.ts index 123ec7603a..3566584f06 100644 --- a/src/examples/zkprogram/program-with-non-pure-input.ts +++ b/src/examples/zkprogram/program-with-non-pure-input.ts @@ -15,7 +15,7 @@ let MyProgram = ZkProgram({ privateInputs: [], async method(input: MyStruct) { //update input in circuit - input.label = 'inCircuit'; + input.label = 'in-circuit'; return { publicOutput: input, }; @@ -36,4 +36,4 @@ let { proof } = await MyProgram.baseCase(input); let ok = await MyProgram.verify(proof); assert(ok, 'proof not valid!'); -assert(proof.publicOutput.label === 'inCircuit'); +assert(proof.publicOutput.label === 'in-circuit'); From dc2dd4f376b5b1160d18f258368cdd2a2f77af50 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 13 Nov 2024 23:26:07 +0700 Subject: [PATCH 135/328] feat(zkprogram.ts): remove setNonPureInput and getNonPureInput functions from cache in favor of snarkContext --- src/lib/proof-system/zkprogram.ts | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 8f818f139a..0e769b9439 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -90,14 +90,6 @@ const Void: ProvablePureExtended = EmptyVoid(); function createProgramState() { let methodCache: Map = new Map(); return { - setNonPureInput(value: any[]) { - methodCache.set('nonPureInput', value); - }, - getNonPureInput(): any[] { - let entry = methodCache.get('nonPureInput'); - if (entry === undefined) throw Error(`Non-pure input not defined`); - return entry as any[]; - }, setNonPureOutput(value: any[]) { methodCache.set('nonPureOutput', value); }, @@ -419,9 +411,6 @@ function ZkProgram< publicInputType, publicInput )); - - // store publicInput auxilary data in programState cache - programState.setNonPureInput(publicInputAux); } else { publicInputFields = toFieldConsts(publicInputType, publicInput); } From d9277ddb3a9ea17ab389b5e47ed100e126ed880b Mon Sep 17 00:00:00 2001 From: ymekuria Date: Thu, 14 Nov 2024 00:01:41 +0700 Subject: [PATCH 136/328] refactor(zkprogram.ts): update methodCache key from 'nonPureOutput' to '__nonPureOutput__' to avoid collisions --- src/lib/proof-system/zkprogram.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 0e769b9439..9efb896edb 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -91,10 +91,10 @@ function createProgramState() { let methodCache: Map = new Map(); return { setNonPureOutput(value: any[]) { - methodCache.set('nonPureOutput', value); + methodCache.set('__nonPureOutput__', value); }, getNonPureOutput(): any[] { - let entry = methodCache.get('nonPureOutput'); + let entry = methodCache.get('__nonPureOutput__'); if (entry === undefined) throw Error(`Non-pure output not defined`); return entry as any[]; }, From c0bed414746d7f9dedc9b2ecef8f5fa2f65250da Mon Sep 17 00:00:00 2001 From: ymekuria Date: Mon, 18 Nov 2024 20:53:08 +0700 Subject: [PATCH 137/328] feat(zkprogram.ts): update nonPureInputExists check to correctly handle auxiliary inputs with length 0 --- src/lib/proof-system/zkprogram.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 9efb896edb..22c76d0af5 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -95,6 +95,7 @@ function createProgramState() { }, getNonPureOutput(): any[] { let entry = methodCache.get('__nonPureOutput__'); + console.log('entry in get nonPureOutput', entry); if (entry === undefined) throw Error(`Non-pure output not defined`); return entry as any[]; }, @@ -401,8 +402,11 @@ function ZkProgram< ); } - let nonPureInputExists = - publicInputType.toAuxiliary(publicInput).length !== 0; + console.log('aux before check', publicInputType.toAuxiliary(publicInput)); + let nonPureInputExists = publicInputType + .toAuxiliary(publicInput) + .some((aux) => aux.length !== 0); + console.log('nonPure Input Exists', nonPureInputExists); let publicInputFields, publicInputAux; if (nonPureInputExists) { @@ -447,6 +451,11 @@ function ZkProgram< let publicOutput; let [publicOutputFields, proof] = MlPair.from(result); if (nonPureInputExists) { + console.log('auxInputData', publicInputAux); + console.log( + 'nonPureInputExists before calling getNonPureOutput', + nonPureInputExists + ); let nonPureOutput = programState.getNonPureOutput(); publicOutput = fromFieldConsts( From b79a0555d5d1c001e5a787df5dcb79d578f5fd93 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Mon, 18 Nov 2024 20:55:59 +0700 Subject: [PATCH 138/328] refactor(zkprogram.ts): remove unnecessary console.log statements for better code cleanliness and readability --- src/lib/proof-system/zkprogram.ts | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 22c76d0af5..4b40d023ea 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -95,7 +95,6 @@ function createProgramState() { }, getNonPureOutput(): any[] { let entry = methodCache.get('__nonPureOutput__'); - console.log('entry in get nonPureOutput', entry); if (entry === undefined) throw Error(`Non-pure output not defined`); return entry as any[]; }, @@ -402,12 +401,10 @@ function ZkProgram< ); } - console.log('aux before check', publicInputType.toAuxiliary(publicInput)); let nonPureInputExists = publicInputType .toAuxiliary(publicInput) .some((aux) => aux.length !== 0); - console.log('nonPure Input Exists', nonPureInputExists); let publicInputFields, publicInputAux; if (nonPureInputExists) { // serialize publicInput into pure provable field elements and auxilary data @@ -421,7 +418,6 @@ function ZkProgram< let previousProofs = MlArray.to(getPreviousProofsForProver(args)); - console.log('auxdata before entering snarkContext ', publicInputAux); let id = snarkContext.enter({ witnesses: args, inProver: true, @@ -451,11 +447,6 @@ function ZkProgram< let publicOutput; let [publicOutputFields, proof] = MlPair.from(result); if (nonPureInputExists) { - console.log('auxInputData', publicInputAux); - console.log( - 'nonPureInputExists before calling getNonPureOutput', - nonPureInputExists - ); let nonPureOutput = programState.getNonPureOutput(); publicOutput = fromFieldConsts( @@ -892,12 +883,10 @@ function picklesRuleFromFunction( if (publicInputType === Undefined || publicInputType === Void) { result = (await func(...finalArgs)) as any; } else { - console.log('auxData before input', auxInputData); let input = fromFieldVars(publicInputType, publicInput, auxInputData); result = (await func(input, ...finalArgs)) as any; } - console.log('result input', result); if (result?.publicOutput) { // store the nonPure auxiliary data in program state cache if it exists let nonPureOutput = publicOutputType.toAuxiliary(result.publicOutput); From eb61e8caf661a10b0fe55c05b04b3dcfc5d1250a Mon Sep 17 00:00:00 2001 From: ymekuria Date: Mon, 18 Nov 2024 23:47:10 +0700 Subject: [PATCH 139/328] chore(bindings): update subproject commit reference to 015333ff2 for consistency --- src/bindings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bindings b/src/bindings index acc5a7c566..015333ff22 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit acc5a7c56645ea46f58e698bca75a011407d45b0 +Subproject commit 015333ff220ed723f12580acfd6a6beab593072f From 4fcc4289f99d40c6c3e8e878196998ed284abc7b Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 20 Nov 2024 12:58:38 +0800 Subject: [PATCH 140/328] chore(bindings): update subproject commit reference to 015333ff2 for consistency --- src/bindings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bindings b/src/bindings index 2c62a9a755..015333ff22 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit 2c62a9a755f1b128f89cc2131814df7157f68109 +Subproject commit 015333ff220ed723f12580acfd6a6beab593072f From 27d124bcd7b6a23b747d14888045e6710b034114 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 20 Nov 2024 13:01:26 +0800 Subject: [PATCH 141/328] refactor(zkprogram.ts): update the reset method argument from 'nonPureOutput' to '__nonPureOutput__' to match the expected value and improve clarity --- src/lib/proof-system/zkprogram.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 4b40d023ea..137238ab1e 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -455,7 +455,7 @@ function ZkProgram< nonPureOutput ); - programState.reset('nonPureOutput'); + programState.reset('__nonPureOutput__'); } else { publicOutput = fromFieldConsts(publicOutputType, publicOutputFields); } From 04d9ae273dca0ffb060d7c34373dcb856ff2085f Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 20 Nov 2024 13:28:53 +0800 Subject: [PATCH 142/328] refactor(zkprogram.ts): remove unnecessary empty lines for better code readability and consistency --- src/lib/proof-system/zkprogram.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 137238ab1e..ac4717079b 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -98,11 +98,9 @@ function createProgramState() { if (entry === undefined) throw Error(`Non-pure output not defined`); return entry as any[]; }, - setAuxiliaryOutput(value: unknown, methodName: string) { methodCache.set(methodName, value); }, - getAuxiliaryOutput(methodName: string): unknown { let entry = methodCache.get(methodName); if (entry === undefined) From 5866a011f681cc591de8ad1a7a1abdf406d4dc8e Mon Sep 17 00:00:00 2001 From: boray Date: Wed, 20 Nov 2024 11:57:56 +0300 Subject: [PATCH 143/328] test: add recursive program to e2e testing --- src/build/e2e-tests-build-helper.js | 40 ++++++++++++++----- src/examples/zkprogram/program-with-input.ts | 2 +- .../html/on-chain-state-mgmt-zkapp-ui.html | 4 ++ .../on-chain-state-mgmt-zkapp-ui.js | 18 +++++++++ tests/on-chain-state-mgmt-zkapp-ui.spec.ts | 10 +++++ tests/pages/on-chain-state-mgmt-zkapp.ts | 11 +++++ 6 files changed, 73 insertions(+), 12 deletions(-) diff --git a/src/build/e2e-tests-build-helper.js b/src/build/e2e-tests-build-helper.js index 3709c514e8..d2b9adeca1 100644 --- a/src/build/e2e-tests-build-helper.js +++ b/src/build/e2e-tests-build-helper.js @@ -1,14 +1,32 @@ import replace from 'replace-in-file'; -const options = { - files: './dist/web/examples/zkapps/**/*.js', - from: /from 'o1js'/g, - to: "from '../../../index.js'", -}; - -try { - const results = await replace(options); - console.log('Replacement results:', results); -} catch (error) { - console.error('Error occurred:', error); +const replaceOptions = [ + { + files: './dist/web/examples/zkapps/**/*.js', + from: /from 'o1js'/g, + to: "from '../../../index.js'", + }, + { + files: './dist/web/examples/zkprogram/*.js', + from: /from 'o1js'/g, + to: "from '../../index.js'", + }, +]; + +async function performReplacement(options) { + try { + const results = await replace(options); + console.log(`Replacement results for ${options.files}:`, results); + } catch (error) { + console.error(`Error occurred while replacing in ${options.files}:`, error); + } +} + +async function main() { + for (const options of replaceOptions) { + await performReplacement(options); + } } + +main(); + diff --git a/src/examples/zkprogram/program-with-input.ts b/src/examples/zkprogram/program-with-input.ts index a6117771b3..a1a6a71cde 100644 --- a/src/examples/zkprogram/program-with-input.ts +++ b/src/examples/zkprogram/program-with-input.ts @@ -8,7 +8,7 @@ import { Provable, } from 'o1js'; -let MyProgram = ZkProgram({ +export let MyProgram = ZkProgram({ name: 'example-with-input', publicInput: Field, diff --git a/tests/artifacts/html/on-chain-state-mgmt-zkapp-ui.html b/tests/artifacts/html/on-chain-state-mgmt-zkapp-ui.html index b9bad32a17..980822b28c 100644 --- a/tests/artifacts/html/on-chain-state-mgmt-zkapp-ui.html +++ b/tests/artifacts/html/on-chain-state-mgmt-zkapp-ui.html @@ -25,6 +25,10 @@

UI for the On-Chain State Management zkApp


+

zkProgram Management

+
+ +

zkApp Management

diff --git a/tests/artifacts/javascript/on-chain-state-mgmt-zkapp-ui.js b/tests/artifacts/javascript/on-chain-state-mgmt-zkapp-ui.js index bfeed49252..60b3fd340b 100644 --- a/tests/artifacts/javascript/on-chain-state-mgmt-zkapp-ui.js +++ b/tests/artifacts/javascript/on-chain-state-mgmt-zkapp-ui.js @@ -3,8 +3,10 @@ import { adminPrivateKey, HelloWorld, } from './examples/zkapps/hello-world/hello-world.js'; +import { MyProgram } from './examples/zkprogram/program-with-input.js' import { AccountUpdate, Field, Mina, verify } from './index.js'; +const compileButton = document.querySelector('#compileButton'); const deployButton = document.querySelector('#deployButton'); const updateButton = document.querySelector('#updateButton'); const clearEventsButton = document.querySelector('#clearEventsButton'); @@ -25,6 +27,22 @@ const contractAddress = Mina.TestPublicKey.random(); const contract = new HelloWorld(contractAddress); let verificationKey = null; +compileButton.addEventListener('click', async () => { + compileButton.disabled = true; + + logEvents('Compiling ZkProgram', eventsContainer); + + try { + await MyProgram.compile(); + logEvents('ZkProgram compiled successfully!', eventsContainer); + } catch (exception) { + logEvents(`Compilation failure: ${exception.message}`, eventsContainer); + console.log(exception); + } + + compileButton.disabled = false; +}); + deployButton.addEventListener('click', async () => { deployButton.disabled = true; diff --git a/tests/on-chain-state-mgmt-zkapp-ui.spec.ts b/tests/on-chain-state-mgmt-zkapp-ui.spec.ts index 7fba7fd26d..76a7c72e4b 100644 --- a/tests/on-chain-state-mgmt-zkapp-ui.spec.ts +++ b/tests/on-chain-state-mgmt-zkapp-ui.spec.ts @@ -8,6 +8,16 @@ test.describe('On-Chain State Management zkApp UI', () => { await onChainStateMgmtZkAppPage.checkO1jsInitialization(); }); + test('should compile zkProgram', async ({ + onChainStateMgmtZkAppPage, + }) => { + await onChainStateMgmtZkAppPage.goto(); + await onChainStateMgmtZkAppPage.checkO1jsInitialization(); + await onChainStateMgmtZkAppPage.compileZkProgram(); + await onChainStateMgmtZkAppPage.checkZkProgramCompilation(); + }); + + test('should fail to update account state since zkApp was not yet deployed', async ({ onChainStateMgmtZkAppPage, }) => { diff --git a/tests/pages/on-chain-state-mgmt-zkapp.ts b/tests/pages/on-chain-state-mgmt-zkapp.ts index bf1a8027d9..db36d011d2 100644 --- a/tests/pages/on-chain-state-mgmt-zkapp.ts +++ b/tests/pages/on-chain-state-mgmt-zkapp.ts @@ -2,6 +2,7 @@ import { expect, type Locator, type Page } from '@playwright/test'; export class OnChainStateMgmtZkAppPage { readonly page: Page; + readonly compileButton: Locator; readonly deployButton: Locator; readonly updateButton: Locator; readonly clearEventsButton: Locator; @@ -11,6 +12,7 @@ export class OnChainStateMgmtZkAppPage { constructor(page: Page) { this.page = page; + this.compileButton = page.locator('button[id="compileButton"]'); this.deployButton = page.locator('button[id="deployButton"]'); this.updateButton = page.locator('button[id="updateButton"]'); this.clearEventsButton = page.locator('button[id="clearEventsButton"]'); @@ -23,6 +25,10 @@ export class OnChainStateMgmtZkAppPage { await this.page.goto('/on-chain-state-mgmt-zkapp-ui.html'); } + async compileZkProgram() { + await this.compileButton.click(); + } + async compileAndDeployZkApp() { await this.deployButton.click(); } @@ -40,6 +46,11 @@ export class OnChainStateMgmtZkAppPage { await expect(this.eventsContainer).toContainText('o1js initialized after'); } + async checkZkProgramCompilation() { + await expect(this.eventsContainer).toContainText('Compiling ZkProgram'); + await expect(this.eventsContainer).toContainText('ZkProgram compiled successfully!'); + } + async checkDeployedZkApp() { await expect(this.eventsContainer).toContainText('Deploying'); await expect(this.eventsContainer).toContainText('Initial state: 2'); From 33e719abf6ba70809d2de14f4bc8973775592e1a Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 20 Nov 2024 18:48:36 +0800 Subject: [PATCH 144/328] refactor(program-with-non-pure-input.ts): remove unnecessary comment line to improve code readability and cleanliness --- src/examples/zkprogram/program-with-non-pure-input.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/examples/zkprogram/program-with-non-pure-input.ts b/src/examples/zkprogram/program-with-non-pure-input.ts index 3566584f06..bdbc7c1f80 100644 --- a/src/examples/zkprogram/program-with-non-pure-input.ts +++ b/src/examples/zkprogram/program-with-non-pure-input.ts @@ -24,8 +24,6 @@ let MyProgram = ZkProgram({ }, }); -// - console.log('compiling MyProgram...'); await MyProgram.compile(); console.log('compile done'); From 0d7c83be4f0813d6513fb1c8e0d858e2dfd48189 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 20 Nov 2024 19:17:31 +0800 Subject: [PATCH 145/328] style(zkprogram.ts): fix typo in comment, change 'auxilary' to 'auxiliary' for consistency and clarity --- src/lib/proof-system/zkprogram.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index ac4717079b..49e4e92b3b 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -405,7 +405,7 @@ function ZkProgram< let publicInputFields, publicInputAux; if (nonPureInputExists) { - // serialize publicInput into pure provable field elements and auxilary data + // serialize publicInput into pure provable field elements and auxiliary data ({ publicInputFields, publicInputAux } = toFieldAndAuxConsts( publicInputType, publicInput From 9c760f03c314e6861877603fbe12558a8933caae Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 20 Nov 2024 20:48:05 +0800 Subject: [PATCH 146/328] feat(zkprogram.ts): handle case where non-pure output is not defined by returning an empty array instead of throwing an error --- src/lib/proof-system/zkprogram.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 49e4e92b3b..9e70df0b43 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -95,7 +95,7 @@ function createProgramState() { }, getNonPureOutput(): any[] { let entry = methodCache.get('__nonPureOutput__'); - if (entry === undefined) throw Error(`Non-pure output not defined`); + if (entry === undefined) return []; return entry as any[]; }, setAuxiliaryOutput(value: unknown, methodName: string) { From bc28e8ee1d0df2819311e45e4de5c5b5714ef80d Mon Sep 17 00:00:00 2001 From: boray Date: Wed, 20 Nov 2024 17:46:12 +0300 Subject: [PATCH 147/328] test: add comments to elaborate why we import MyProgram --- tests/artifacts/javascript/on-chain-state-mgmt-zkapp-ui.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/artifacts/javascript/on-chain-state-mgmt-zkapp-ui.js b/tests/artifacts/javascript/on-chain-state-mgmt-zkapp-ui.js index 60b3fd340b..6848305810 100644 --- a/tests/artifacts/javascript/on-chain-state-mgmt-zkapp-ui.js +++ b/tests/artifacts/javascript/on-chain-state-mgmt-zkapp-ui.js @@ -3,7 +3,10 @@ import { adminPrivateKey, HelloWorld, } from './examples/zkapps/hello-world/hello-world.js'; -import { MyProgram } from './examples/zkprogram/program-with-input.js' +// MyProgram to serve as a test case for recursive ZkProgram compilation. +// This helps to catch any regressions that might occur in the future. +// For more details, refer to: https://github.com/o1-labs/o1js/pull/1906 +import { MyProgram } from './examples/zkprogram/program-with-input.js'; import { AccountUpdate, Field, Mina, verify } from './index.js'; const compileButton = document.querySelector('#compileButton'); From 94d143aef5678e03a3852063d8b911f567fddc92 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Thu, 21 Nov 2024 00:44:02 +0800 Subject: [PATCH 148/328] refactor(zkprogram.ts): unify if else branches into one block for simplicity --- src/lib/proof-system/zkprogram.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 9e70df0b43..55973652be 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -454,8 +454,6 @@ function ZkProgram< ); programState.reset('__nonPureOutput__'); - } else { - publicOutput = fromFieldConsts(publicOutputType, publicOutputFields); } return { From ee75eae29c9c8a82aa755cf745c88a20bea6c241 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Thu, 21 Nov 2024 01:23:34 +0800 Subject: [PATCH 149/328] refactor(zkprogram.ts): remove conditional check for non-pure input in favor of merging if else logic to improve readability --- src/lib/proof-system/zkprogram.ts | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 55973652be..0b77a31f69 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -442,19 +442,17 @@ function ZkProgram< programState.reset(methodIntfs[i].methodName); } - let publicOutput; let [publicOutputFields, proof] = MlPair.from(result); - if (nonPureInputExists) { - let nonPureOutput = programState.getNonPureOutput(); - publicOutput = fromFieldConsts( - publicOutputType, - publicOutputFields, - nonPureOutput - ); + let nonPureOutput = programState.getNonPureOutput(); - programState.reset('__nonPureOutput__'); - } + let publicOutput = fromFieldConsts( + publicOutputType, + publicOutputFields, + nonPureOutput + ); + + programState.reset('__nonPureOutput__'); return { proof: new ProgramProof({ From 805116e90ac8f7f80cfae0306ce46bd541514935 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Thu, 21 Nov 2024 01:27:26 +0800 Subject: [PATCH 150/328] feat(program-with-non-pure-input.ts): add a new ZkProgram NonPureOutputProgram example to handle case with only non-pure output --- .../zkprogram/program-with-non-pure-input.ts | 43 +++++++++++++++---- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/src/examples/zkprogram/program-with-non-pure-input.ts b/src/examples/zkprogram/program-with-non-pure-input.ts index bdbc7c1f80..99e959e29a 100644 --- a/src/examples/zkprogram/program-with-non-pure-input.ts +++ b/src/examples/zkprogram/program-with-non-pure-input.ts @@ -5,8 +5,8 @@ class MyStruct extends Struct({ value: Field, }) {} -let MyProgram = ZkProgram({ - name: 'example-with-non-pure-inputs', +let NonPureIOprogram = ZkProgram({ + name: 'example-with-non-pure-io', publicInput: MyStruct, publicOutput: MyStruct, @@ -24,14 +24,39 @@ let MyProgram = ZkProgram({ }, }); -console.log('compiling MyProgram...'); -await MyProgram.compile(); -console.log('compile done'); +let NonPureOutputProgram = ZkProgram({ + name: 'example-with-non-pure-output', + publicOutput: MyStruct, + methods: { + baseCase: { + privateInputs: [], + async method() { + return { + publicOutput: new MyStruct({ label: 'output', value: Field(5) }), + }; + }, + }, + }, +}); + +console.log('compiling NonPureIOprogram...'); +await NonPureIOprogram.compile(); +console.log('compile done'); let input = new MyStruct({ label: 'input', value: Field(5) }); -let { proof } = await MyProgram.baseCase(input); -let ok = await MyProgram.verify(proof); +let result1 = await NonPureIOprogram.baseCase(input); +let isProof1Valid = await NonPureIOprogram.verify(result1.proof); +assert(isProof1Valid, 'proof not valid!'); +assert(result1.proof.publicOutput.label === 'in-circuit'); +console.log('proof IO', result1.proof); + +console.log('compiling NonPureOutputProgram...'); +await NonPureOutputProgram.compile(); +console.log('compile done'); -assert(ok, 'proof not valid!'); -assert(proof.publicOutput.label === 'in-circuit'); +let result2 = await NonPureOutputProgram.baseCase(); +let isProof2Valid = await NonPureOutputProgram.verify(result2.proof); +assert(isProof2Valid, 'proof not valid!'); +assert(result2.proof.publicOutput.label === 'output'); +console.log('proof O', result2.proof); From c5bcc5e5f012e2e4db2cbb3cc6b3ea26d3d8c970 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Thu, 21 Nov 2024 01:46:46 +0800 Subject: [PATCH 151/328] feat(program-with-non-pure-input.ts): add NonPureInputProgram to example --- .../zkprogram/program-with-non-pure-input.ts | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/examples/zkprogram/program-with-non-pure-input.ts b/src/examples/zkprogram/program-with-non-pure-input.ts index 99e959e29a..420d08c9ea 100644 --- a/src/examples/zkprogram/program-with-non-pure-input.ts +++ b/src/examples/zkprogram/program-with-non-pure-input.ts @@ -40,6 +40,17 @@ let NonPureOutputProgram = ZkProgram({ }, }); +let NonPureInputProgram = ZkProgram({ + name: 'example-with-non-pure-input', + publicInput: MyStruct, + + methods: { + baseCase: { + privateInputs: [], + async method(input) {}, + }, + }, +}); console.log('compiling NonPureIOprogram...'); await NonPureIOprogram.compile(); console.log('compile done'); @@ -60,3 +71,13 @@ let isProof2Valid = await NonPureOutputProgram.verify(result2.proof); assert(isProof2Valid, 'proof not valid!'); assert(result2.proof.publicOutput.label === 'output'); console.log('proof O', result2.proof); + +console.log('compiling NonPureInputProgram...'); +await NonPureInputProgram.compile(); +console.log('compile done'); + +let result3 = await NonPureInputProgram.baseCase(input); +let isProof3Valid = await NonPureInputProgram.verify(result3.proof); +assert(isProof3Valid, 'proof not valid!'); +assert(result3.proof.publicInput.label === 'input'); +console.log('proof O', result3.proof); From db35a1ca49e98cb092da88167f2a6b150e0e29de Mon Sep 17 00:00:00 2001 From: boray Date: Wed, 20 Nov 2024 20:53:52 +0300 Subject: [PATCH 152/328] test: add recursive zkprogram --- src/examples/zkprogram/program-with-input.ts | 2 +- src/examples/zkprogram/recursive-program.ts | 23 +++++++++++++++++++ .../on-chain-state-mgmt-zkapp-ui.js | 7 ++---- 3 files changed, 26 insertions(+), 6 deletions(-) create mode 100644 src/examples/zkprogram/recursive-program.ts diff --git a/src/examples/zkprogram/program-with-input.ts b/src/examples/zkprogram/program-with-input.ts index a1a6a71cde..a6117771b3 100644 --- a/src/examples/zkprogram/program-with-input.ts +++ b/src/examples/zkprogram/program-with-input.ts @@ -8,7 +8,7 @@ import { Provable, } from 'o1js'; -export let MyProgram = ZkProgram({ +let MyProgram = ZkProgram({ name: 'example-with-input', publicInput: Field, diff --git a/src/examples/zkprogram/recursive-program.ts b/src/examples/zkprogram/recursive-program.ts new file mode 100644 index 0000000000..b6b6f3b61b --- /dev/null +++ b/src/examples/zkprogram/recursive-program.ts @@ -0,0 +1,23 @@ +import { SelfProof, Field, ZkProgram } from 'o1js'; + +export const RecusiveProgram = ZkProgram({ + name: 'recursive-program', + publicInput: Field, + + methods: { + baseCase: { + privateInputs: [], + async method(input: Field) { + input.assertEquals(Field(0)); + }, + }, + + inductiveCase: { + privateInputs: [SelfProof], + async method(input: Field, earlierProof: SelfProof) { + earlierProof.verify(); + earlierProof.publicInput.add(1).assertEquals(input); + }, + }, + }, +}); diff --git a/tests/artifacts/javascript/on-chain-state-mgmt-zkapp-ui.js b/tests/artifacts/javascript/on-chain-state-mgmt-zkapp-ui.js index 6848305810..86392c0d0c 100644 --- a/tests/artifacts/javascript/on-chain-state-mgmt-zkapp-ui.js +++ b/tests/artifacts/javascript/on-chain-state-mgmt-zkapp-ui.js @@ -3,10 +3,7 @@ import { adminPrivateKey, HelloWorld, } from './examples/zkapps/hello-world/hello-world.js'; -// MyProgram to serve as a test case for recursive ZkProgram compilation. -// This helps to catch any regressions that might occur in the future. -// For more details, refer to: https://github.com/o1-labs/o1js/pull/1906 -import { MyProgram } from './examples/zkprogram/program-with-input.js'; +import { RecursiveProgram } from './examples/zkprogram/recursive-program.js'; import { AccountUpdate, Field, Mina, verify } from './index.js'; const compileButton = document.querySelector('#compileButton'); @@ -36,7 +33,7 @@ compileButton.addEventListener('click', async () => { logEvents('Compiling ZkProgram', eventsContainer); try { - await MyProgram.compile(); + await RecursiveProgram.compile(); logEvents('ZkProgram compiled successfully!', eventsContainer); } catch (exception) { logEvents(`Compilation failure: ${exception.message}`, eventsContainer); From d9588a902f663c100ed6430e916e7d7055c8912a Mon Sep 17 00:00:00 2001 From: ymekuria Date: Thu, 21 Nov 2024 01:58:28 +0800 Subject: [PATCH 153/328] refactor(program-with-non-pure-input.ts): refactor code to destructure proof object for better readability and consistency in accessing proof properties --- .../zkprogram/program-with-non-pure-input.ts | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/examples/zkprogram/program-with-non-pure-input.ts b/src/examples/zkprogram/program-with-non-pure-input.ts index 420d08c9ea..a9908d9b42 100644 --- a/src/examples/zkprogram/program-with-non-pure-input.ts +++ b/src/examples/zkprogram/program-with-non-pure-input.ts @@ -55,29 +55,29 @@ console.log('compiling NonPureIOprogram...'); await NonPureIOprogram.compile(); console.log('compile done'); let input = new MyStruct({ label: 'input', value: Field(5) }); - -let result1 = await NonPureIOprogram.baseCase(input); -let isProof1Valid = await NonPureIOprogram.verify(result1.proof); +let proof; +({ proof } = await NonPureIOprogram.baseCase(input)); +let isProof1Valid = await NonPureIOprogram.verify(proof); assert(isProof1Valid, 'proof not valid!'); -assert(result1.proof.publicOutput.label === 'in-circuit'); -console.log('proof IO', result1.proof); +assert(proof.publicOutput.label === 'in-circuit'); +console.log('i/o proof', proof); console.log('compiling NonPureOutputProgram...'); await NonPureOutputProgram.compile(); console.log('compile done'); -let result2 = await NonPureOutputProgram.baseCase(); -let isProof2Valid = await NonPureOutputProgram.verify(result2.proof); +({ proof } = await NonPureOutputProgram.baseCase()); +let isProof2Valid = await NonPureOutputProgram.verify(proof); assert(isProof2Valid, 'proof not valid!'); -assert(result2.proof.publicOutput.label === 'output'); -console.log('proof O', result2.proof); +assert(proof.publicOutput.label === 'output'); +console.log('output proof', proof); console.log('compiling NonPureInputProgram...'); await NonPureInputProgram.compile(); console.log('compile done'); -let result3 = await NonPureInputProgram.baseCase(input); -let isProof3Valid = await NonPureInputProgram.verify(result3.proof); +({ proof } = await NonPureInputProgram.baseCase(input)); +let isProof3Valid = await NonPureInputProgram.verify(proof); assert(isProof3Valid, 'proof not valid!'); -assert(result3.proof.publicInput.label === 'input'); -console.log('proof O', result3.proof); +assert(proof.publicInput.label === 'input'); +console.log('input proof', proof); From 6ea6545015cc672297866d64577620eddbfe17a6 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Thu, 21 Nov 2024 02:22:39 +0800 Subject: [PATCH 154/328] refactor(zkprogram.ts): simplify serialization of publicInputFields and publicInputAux by merging non-pure and pure input branch cases into one. --- src/lib/proof-system/zkprogram.ts | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 0b77a31f69..301463d799 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -403,16 +403,10 @@ function ZkProgram< .toAuxiliary(publicInput) .some((aux) => aux.length !== 0); - let publicInputFields, publicInputAux; - if (nonPureInputExists) { - // serialize publicInput into pure provable field elements and auxiliary data - ({ publicInputFields, publicInputAux } = toFieldAndAuxConsts( - publicInputType, - publicInput - )); - } else { - publicInputFields = toFieldConsts(publicInputType, publicInput); - } + let { publicInputFields, publicInputAux } = toFieldAndAuxConsts( + publicInputType, + publicInput + ); let previousProofs = MlArray.to(getPreviousProofsForProver(args)); From e8b2902163266e067357ffd7894cc2ba0f53904d Mon Sep 17 00:00:00 2001 From: ymekuria Date: Thu, 21 Nov 2024 02:25:49 +0800 Subject: [PATCH 155/328] refactor(zkprogram.ts): remove unused nonPureInputExists conditional check --- src/lib/proof-system/zkprogram.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 301463d799..ba0891992e 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -399,10 +399,6 @@ function ZkProgram< ); } - let nonPureInputExists = publicInputType - .toAuxiliary(publicInput) - .some((aux) => aux.length !== 0); - let { publicInputFields, publicInputAux } = toFieldAndAuxConsts( publicInputType, publicInput From 5af3bd69def715001c8a4c6cc5b20a34eb2dec1c Mon Sep 17 00:00:00 2001 From: ymekuria Date: Thu, 21 Nov 2024 02:29:27 +0800 Subject: [PATCH 156/328] refactor(zkprogram.ts): remove unused toFieldVars function to clean up code and improve readability --- src/lib/proof-system/zkprogram.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index ba0891992e..92ebf9f872 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -1005,10 +1005,6 @@ function fromFieldVars( return type.fromFields(MlFieldArray.from(fields), auxData); } -function toFieldVars(type: ProvablePure, value: T) { - return MlFieldArray.to(type.toFields(value)); -} - function fromFieldConsts( type: Provable, fields: MlFieldConstArray, From e54cb3e01a26e395ab277532ffd5bae323eba12b Mon Sep 17 00:00:00 2001 From: boray Date: Wed, 20 Nov 2024 21:39:02 +0300 Subject: [PATCH 157/328] test: format helper --- src/build/e2e-tests-build-helper.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/build/e2e-tests-build-helper.js b/src/build/e2e-tests-build-helper.js index d2b9adeca1..f21d3f0fff 100644 --- a/src/build/e2e-tests-build-helper.js +++ b/src/build/e2e-tests-build-helper.js @@ -29,4 +29,3 @@ async function main() { } main(); - From fee51bc2b0fee198ea6ffcded5b40ad5511af70e Mon Sep 17 00:00:00 2001 From: ymekuria Date: Thu, 21 Nov 2024 02:58:33 +0800 Subject: [PATCH 158/328] chore(bindings): update subproject commit reference to e172bf02e to track latest changes --- src/bindings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bindings b/src/bindings index 015333ff22..e172bf02e7 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit 015333ff220ed723f12580acfd6a6beab593072f +Subproject commit e172bf02e79ce8993c6dbac06b238822313a7441 From bd529b8e14f0d30c659628db3690daf5eb5e805a Mon Sep 17 00:00:00 2001 From: boray Date: Wed, 20 Nov 2024 23:01:47 +0300 Subject: [PATCH 159/328] test: fix typo --- src/examples/zkprogram/recursive-program.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/examples/zkprogram/recursive-program.ts b/src/examples/zkprogram/recursive-program.ts index b6b6f3b61b..0308266cd8 100644 --- a/src/examples/zkprogram/recursive-program.ts +++ b/src/examples/zkprogram/recursive-program.ts @@ -1,6 +1,6 @@ import { SelfProof, Field, ZkProgram } from 'o1js'; -export const RecusiveProgram = ZkProgram({ +export const RecursiveProgram = ZkProgram({ name: 'recursive-program', publicInput: Field, From 6260b56ddf0491dee52755885c93907c19627c36 Mon Sep 17 00:00:00 2001 From: boray Date: Wed, 20 Nov 2024 23:05:23 +0300 Subject: [PATCH 160/328] test: fix format to trigger gh actions --- tests/pages/on-chain-state-mgmt-zkapp.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/pages/on-chain-state-mgmt-zkapp.ts b/tests/pages/on-chain-state-mgmt-zkapp.ts index db36d011d2..d9e2e9b45b 100644 --- a/tests/pages/on-chain-state-mgmt-zkapp.ts +++ b/tests/pages/on-chain-state-mgmt-zkapp.ts @@ -48,7 +48,9 @@ export class OnChainStateMgmtZkAppPage { async checkZkProgramCompilation() { await expect(this.eventsContainer).toContainText('Compiling ZkProgram'); - await expect(this.eventsContainer).toContainText('ZkProgram compiled successfully!'); + await expect(this.eventsContainer).toContainText( + 'ZkProgram compiled successfully!' + ); } async checkDeployedZkApp() { From 7f8b6ec1a2ea6ef3a4d1eb917e150a21cb807a37 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Thu, 21 Nov 2024 23:22:37 +0800 Subject: [PATCH 161/328] feat(zkprogram.ts): revert changes ci fix --- src/lib/proof-system/zkprogram.ts | 40 +++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 92ebf9f872..55973652be 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -399,10 +399,20 @@ function ZkProgram< ); } - let { publicInputFields, publicInputAux } = toFieldAndAuxConsts( - publicInputType, - publicInput - ); + let nonPureInputExists = publicInputType + .toAuxiliary(publicInput) + .some((aux) => aux.length !== 0); + + let publicInputFields, publicInputAux; + if (nonPureInputExists) { + // serialize publicInput into pure provable field elements and auxiliary data + ({ publicInputFields, publicInputAux } = toFieldAndAuxConsts( + publicInputType, + publicInput + )); + } else { + publicInputFields = toFieldConsts(publicInputType, publicInput); + } let previousProofs = MlArray.to(getPreviousProofsForProver(args)); @@ -432,17 +442,19 @@ function ZkProgram< programState.reset(methodIntfs[i].methodName); } + let publicOutput; let [publicOutputFields, proof] = MlPair.from(result); + if (nonPureInputExists) { + let nonPureOutput = programState.getNonPureOutput(); - let nonPureOutput = programState.getNonPureOutput(); - - let publicOutput = fromFieldConsts( - publicOutputType, - publicOutputFields, - nonPureOutput - ); + publicOutput = fromFieldConsts( + publicOutputType, + publicOutputFields, + nonPureOutput + ); - programState.reset('__nonPureOutput__'); + programState.reset('__nonPureOutput__'); + } return { proof: new ProgramProof({ @@ -1005,6 +1017,10 @@ function fromFieldVars( return type.fromFields(MlFieldArray.from(fields), auxData); } +function toFieldVars(type: ProvablePure, value: T) { + return MlFieldArray.to(type.toFields(value)); +} + function fromFieldConsts( type: Provable, fields: MlFieldConstArray, From cef2844a47369b1cb0143104fd7f0fafab034bce Mon Sep 17 00:00:00 2001 From: ymekuria Date: Fri, 22 Nov 2024 00:05:05 +0800 Subject: [PATCH 162/328] feat(zkprogram.ts): add changes back --- src/lib/proof-system/zkprogram.ts | 40 ++++++++++--------------------- 1 file changed, 12 insertions(+), 28 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 55973652be..92ebf9f872 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -399,20 +399,10 @@ function ZkProgram< ); } - let nonPureInputExists = publicInputType - .toAuxiliary(publicInput) - .some((aux) => aux.length !== 0); - - let publicInputFields, publicInputAux; - if (nonPureInputExists) { - // serialize publicInput into pure provable field elements and auxiliary data - ({ publicInputFields, publicInputAux } = toFieldAndAuxConsts( - publicInputType, - publicInput - )); - } else { - publicInputFields = toFieldConsts(publicInputType, publicInput); - } + let { publicInputFields, publicInputAux } = toFieldAndAuxConsts( + publicInputType, + publicInput + ); let previousProofs = MlArray.to(getPreviousProofsForProver(args)); @@ -442,19 +432,17 @@ function ZkProgram< programState.reset(methodIntfs[i].methodName); } - let publicOutput; let [publicOutputFields, proof] = MlPair.from(result); - if (nonPureInputExists) { - let nonPureOutput = programState.getNonPureOutput(); - publicOutput = fromFieldConsts( - publicOutputType, - publicOutputFields, - nonPureOutput - ); + let nonPureOutput = programState.getNonPureOutput(); - programState.reset('__nonPureOutput__'); - } + let publicOutput = fromFieldConsts( + publicOutputType, + publicOutputFields, + nonPureOutput + ); + + programState.reset('__nonPureOutput__'); return { proof: new ProgramProof({ @@ -1017,10 +1005,6 @@ function fromFieldVars( return type.fromFields(MlFieldArray.from(fields), auxData); } -function toFieldVars(type: ProvablePure, value: T) { - return MlFieldArray.to(type.toFields(value)); -} - function fromFieldConsts( type: Provable, fields: MlFieldConstArray, From 4797e47e818edfe8f615566aa97f33962fc5cc50 Mon Sep 17 00:00:00 2001 From: Geometer1729 <16kuhnb@gmail.com> Date: Thu, 21 Nov 2024 20:49:11 -0500 Subject: [PATCH 163/328] build bindings in derivation --- flake.lock | 488 ++++++++++++++++++++++++++++++++++++++++++++++++++- flake.nix | 165 +++++++++++++---- src/bindings | 2 +- 3 files changed, 615 insertions(+), 40 deletions(-) diff --git a/flake.lock b/flake.lock index 79916af26b..189851c787 100644 --- a/flake.lock +++ b/flake.lock @@ -48,6 +48,31 @@ "type": "github" } }, + "describe-dune_3": { + "inputs": { + "flake-utils": [ + "mina-rev", + "utils" + ], + "nixpkgs": [ + "mina-rev", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1724407960, + "narHash": "sha256-pUKTVMYEtsD1AGlHFTdPourowt+tJ3htKhRu7VALFzc=", + "owner": "o1-labs", + "repo": "describe-dune", + "rev": "be828239c05671209e979f9d5c2e3094e3be7a46", + "type": "github" + }, + "original": { + "owner": "o1-labs", + "repo": "describe-dune", + "type": "github" + } + }, "dune-nix": { "inputs": { "flake-utils": [ @@ -96,6 +121,31 @@ "type": "github" } }, + "dune-nix_3": { + "inputs": { + "flake-utils": [ + "mina-rev", + "utils" + ], + "nixpkgs": [ + "mina-rev", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1724418497, + "narHash": "sha256-HjTh7o02QhGXmbxmpE5HRWei3H/pyh/NKCMCnucDaYs=", + "owner": "o1-labs", + "repo": "dune-nix", + "rev": "26dc164a4c3976888e13eabd73a210b78505820f", + "type": "github" + }, + "original": { + "owner": "o1-labs", + "repo": "dune-nix", + "type": "github" + } + }, "flake-buildkite-pipeline": { "inputs": { "nixpkgs-lib": "nixpkgs-lib" @@ -114,6 +164,24 @@ "type": "github" } }, + "flake-buildkite-pipeline_2": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib_2" + }, + "locked": { + "lastModified": 1665561509, + "narHash": "sha256-+9KQw0ftpNjezYwbUIcLAvDWekuGSBAs8I2XulcUkT4=", + "owner": "tweag", + "repo": "flake-buildkite-pipeline", + "rev": "c836a5a449973dd04a80f6741863ceb43ec414c9", + "type": "github" + }, + "original": { + "owner": "tweag", + "repo": "flake-buildkite-pipeline", + "type": "github" + } + }, "flake-compat": { "flake": false, "locked": { @@ -146,6 +214,38 @@ "type": "github" } }, + "flake-compat_3": { + "flake": false, + "locked": { + "lastModified": 1668681692, + "narHash": "sha256-Ht91NGdewz8IQLtWZ9LCeNXMSXHUss+9COoqu6JLmXU=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "009399224d5e398d03b22badca40a37ac85412a1", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_4": { + "flake": false, + "locked": { + "lastModified": 1627913399, + "narHash": "sha256-hY8g6H2KFL8ownSiFeMOjwPC8P0ueXpCVEbxgda3pko=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "12c64ca55c1014cdc1b16ed5a804aa8576601ff2", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, "flake-utils": { "inputs": { "systems": "systems" @@ -209,6 +309,51 @@ "type": "github" } }, + "flake-utils_5": { + "locked": { + "lastModified": 1623875721, + "narHash": "sha256-A8BU7bjS5GirpAUv4QA+QnJ4CceLHkcXdRp4xITDB0s=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "f7e004a55b120c02ecb6219596820fcd32ca8772", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_6": { + "locked": { + "lastModified": 1638122382, + "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_7": { + "locked": { + "lastModified": 1644229661, + "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, "flockenzeit": { "locked": { "lastModified": 1671184471, @@ -224,6 +369,21 @@ "type": "github" } }, + "flockenzeit_2": { + "locked": { + "lastModified": 1671184471, + "narHash": "sha256-oTsIo40BxHG8ZcMNwJybV68F8CLNdfY9HKFzEBzeJ6A=", + "owner": "balsoft", + "repo": "Flockenzeit", + "rev": "0409dcd0cc87feebd211c529171d61b89f10d9b3", + "type": "github" + }, + "original": { + "owner": "balsoft", + "repo": "Flockenzeit", + "type": "github" + } + }, "gitignore-nix": { "inputs": { "nixpkgs": [ @@ -245,6 +405,27 @@ "type": "github" } }, + "gitignore-nix_2": { + "inputs": { + "nixpkgs": [ + "mina-rev", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1660459072, + "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, "mina": { "inputs": { "describe-dune": "describe-dune_2", @@ -265,8 +446,8 @@ "utils": "utils" }, "locked": { - "lastModified": 1731611028, - "narHash": "sha256-sehBPO+H9mtShGb3KNhdDVHj0pogt/tmiL9tc2ICkaU=", + "lastModified": 1732222139, + "narHash": "sha256-4LLy5VMM5TK4LpQXEBiA8ziwYyqGx2ZAuunXGCDpraQ=", "path": "src/mina", "type": "path" }, @@ -275,6 +456,38 @@ "type": "path" } }, + "mina-rev": { + "inputs": { + "describe-dune": "describe-dune_3", + "dune-nix": "dune-nix_3", + "flake-buildkite-pipeline": "flake-buildkite-pipeline_2", + "flake-compat": "flake-compat_3", + "flockenzeit": "flockenzeit_2", + "gitignore-nix": "gitignore-nix_2", + "mix-to-nix": "mix-to-nix_2", + "nix-filter": "nix-filter_2", + "nix-npm-buildPackage": "nix-npm-buildPackage_2", + "nix-utils": "nix-utils_2", + "nixpkgs": "nixpkgs_4", + "nixpkgs-mozilla": "nixpkgs-mozilla_2", + "o1-opam-repository": "o1-opam-repository_2", + "opam-nix": "opam-nix_2", + "opam-repository": "opam-repository_2", + "utils": "utils_2" + }, + "locked": { + "lastModified": 1729507624, + "narHash": "sha256-DudL1W06R1K0HYyetAVZSzao5B5fjS/rS6cMfCBhiqE=", + "rev": "6899054b745c1323b9d5bcaa62c00bed2ad1ead3", + "revCount": 32900, + "type": "git", + "url": "file:src/mina" + }, + "original": { + "type": "git", + "url": "file:src/mina" + } + }, "mirage-opam-overlays": { "flake": false, "locked": { @@ -291,6 +504,22 @@ "type": "github" } }, + "mirage-opam-overlays_2": { + "flake": false, + "locked": { + "lastModified": 1661959605, + "narHash": "sha256-CPTuhYML3F4J58flfp3ZbMNhkRkVFKmBEYBZY5tnQwA=", + "owner": "dune-universe", + "repo": "mirage-opam-overlays", + "rev": "05f1c1823d891ce4d8adab91f5db3ac51d86dc0b", + "type": "github" + }, + "original": { + "owner": "dune-universe", + "repo": "mirage-opam-overlays", + "type": "github" + } + }, "mix-to-nix": { "locked": { "lastModified": 1643291492, @@ -306,6 +535,21 @@ "type": "github" } }, + "mix-to-nix_2": { + "locked": { + "lastModified": 1643291492, + "narHash": "sha256-B+VIFF8qDJhF5hVMc8PbY/WPzUtbGgjsV1eAxTt5GuQ=", + "owner": "serokell", + "repo": "mix-to-nix", + "rev": "f6f0172b3ac4d32c0e6050a7d805734de0b7adef", + "type": "github" + }, + "original": { + "owner": "serokell", + "repo": "mix-to-nix", + "type": "github" + } + }, "nix-filter": { "locked": { "lastModified": 1666547822, @@ -321,6 +565,21 @@ "type": "github" } }, + "nix-filter_2": { + "locked": { + "lastModified": 1666547822, + "narHash": "sha256-razwnAybPHyoAyhkKCwXdxihIqJi1G6e1XP4FQOJTEs=", + "owner": "numtide", + "repo": "nix-filter", + "rev": "1a3b735e13e90a8d2fd5629f2f8363bd7ffbbec7", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "nix-filter", + "type": "github" + } + }, "nix-npm-buildPackage": { "inputs": { "nixpkgs": [ @@ -342,6 +601,27 @@ "type": "github" } }, + "nix-npm-buildPackage_2": { + "inputs": { + "nixpkgs": [ + "mina-rev", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1670813451, + "narHash": "sha256-v0IvQ35CMKtPreGlxWb1FvFUraJNZd144+MbiDwGoAA=", + "owner": "serokell", + "repo": "nix-npm-buildpackage", + "rev": "ec0365cd14a3359a23b80a9e2531a09afc3488fc", + "type": "github" + }, + "original": { + "owner": "serokell", + "repo": "nix-npm-buildpackage", + "type": "github" + } + }, "nix-utils": { "inputs": { "flake-utils": "flake-utils_2", @@ -361,6 +641,25 @@ "type": "github" } }, + "nix-utils_2": { + "inputs": { + "flake-utils": "flake-utils_5", + "nixpkgs": "nixpkgs_3" + }, + "locked": { + "lastModified": 1632973430, + "narHash": "sha256-9G8zo+0nfYAALV5umCyQR/2hVUFNH10JropBkyxZGGw=", + "owner": "juliosueiras-nix", + "repo": "nix-utils", + "rev": "b44e1ffd726aa03056db9df469efb497d8b9871b", + "type": "github" + }, + "original": { + "owner": "juliosueiras-nix", + "repo": "nix-utils", + "type": "github" + } + }, "nixpkgs": { "locked": { "lastModified": 1629252929, @@ -391,6 +690,21 @@ "type": "github" } }, + "nixpkgs-lib_2": { + "locked": { + "lastModified": 1649551420, + "narHash": "sha256-J/Pn38rBZTszdtTHhhxroQaHADhd5TgbJ53F9j1WTIE=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "3a16841c57b0d3025b21b869cc921a119ce73033", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixpkgs.lib", + "type": "github" + } + }, "nixpkgs-mozilla": { "flake": false, "locked": { @@ -423,6 +737,22 @@ "type": "github" } }, + "nixpkgs-mozilla_3": { + "flake": false, + "locked": { + "lastModified": 1704373101, + "narHash": "sha256-+gi59LRWRQmwROrmE1E2b3mtocwueCQqZ60CwLG+gbg=", + "owner": "mozilla", + "repo": "nixpkgs-mozilla", + "rev": "9b11a87c0cc54e308fa83aac5b4ee1816d5418a2", + "type": "github" + }, + "original": { + "owner": "mozilla", + "repo": "nixpkgs-mozilla", + "type": "github" + } + }, "nixpkgs_2": { "locked": { "lastModified": 1713180868, @@ -440,6 +770,37 @@ } }, "nixpkgs_3": { + "locked": { + "lastModified": 1629252929, + "narHash": "sha256-Aj20gmGBs8TG7pyaQqgbsqAQ6cB+TVuL18Pk3DPBxcQ=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "3788c68def67ca7949e0864c27638d484389363d", + "type": "github" + }, + "original": { + "owner": "nixos", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_4": { + "locked": { + "lastModified": 1713180868, + "narHash": "sha256-5CSnPSCEWeUmrFiLuYIQIPQzPrpCB8x3VhE+oXLRO3k=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "140546acf30a8212a03a88ded8506413fa3b5d21", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-23.11-small", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_5": { "locked": { "lastModified": 1720535198, "narHash": "sha256-zwVvxrdIzralnSbcpghA92tWu2DV2lwv89xZc8MTrbg=", @@ -471,6 +832,22 @@ "type": "github" } }, + "o1-opam-repository_2": { + "flake": false, + "locked": { + "lastModified": 1715294616, + "narHash": "sha256-W2p9Vs8PqpKGvMByxVqpxAljjpEMqNcuNnjMBAAKicI=", + "owner": "o1-labs", + "repo": "opam-repository", + "rev": "38d6995e307c82b3c0b3bc86a867213db724d1c5", + "type": "github" + }, + "original": { + "owner": "o1-labs", + "repo": "opam-repository", + "type": "github" + } + }, "opam-nix": { "inputs": { "flake-compat": "flake-compat_2", @@ -501,6 +878,36 @@ "type": "github" } }, + "opam-nix_2": { + "inputs": { + "flake-compat": "flake-compat_4", + "flake-utils": "flake-utils_6", + "mirage-opam-overlays": "mirage-opam-overlays_2", + "nixpkgs": [ + "mina-rev", + "nixpkgs" + ], + "opam-overlays": "opam-overlays_2", + "opam-repository": [ + "mina-rev", + "opam-repository" + ], + "opam2json": "opam2json_2" + }, + "locked": { + "lastModified": 1712645768, + "narHash": "sha256-9dUh8nElGtC74Q4gIDV6DM0FKgF1oXh0PUkCxdbp+sg=", + "owner": "tweag", + "repo": "opam-nix", + "rev": "464863fba44c7ecc50bd1a2967274482a2c33daf", + "type": "github" + }, + "original": { + "owner": "tweag", + "repo": "opam-nix", + "type": "github" + } + }, "opam-overlays": { "flake": false, "locked": { @@ -517,6 +924,22 @@ "type": "github" } }, + "opam-overlays_2": { + "flake": false, + "locked": { + "lastModified": 1654162756, + "narHash": "sha256-RV68fUK+O3zTx61iiHIoS0LvIk0E4voMp+0SwRg6G6c=", + "owner": "dune-universe", + "repo": "opam-overlays", + "rev": "c8f6ef0fc5272f254df4a971a47de7848cc1c8a4", + "type": "github" + }, + "original": { + "owner": "dune-universe", + "repo": "opam-overlays", + "type": "github" + } + }, "opam-repository": { "flake": false, "locked": { @@ -533,6 +956,22 @@ "type": "github" } }, + "opam-repository_2": { + "flake": false, + "locked": { + "lastModified": 1708601497, + "narHash": "sha256-mDYINTjOiYLN4wT5fGlWTvHFQdWkzY46XUuZWKgmJxY=", + "owner": "ocaml", + "repo": "opam-repository", + "rev": "90d8c520a4f0b035ac51e267a8b33739c5a78b5a", + "type": "github" + }, + "original": { + "owner": "ocaml", + "repo": "opam-repository", + "type": "github" + } + }, "opam2json": { "inputs": { "nixpkgs": [ @@ -555,14 +994,37 @@ "type": "github" } }, + "opam2json_2": { + "inputs": { + "nixpkgs": [ + "mina-rev", + "opam-nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1671540003, + "narHash": "sha256-5pXfbUfpVABtKbii6aaI2EdAZTjHJ2QntEf0QD2O5AM=", + "owner": "tweag", + "repo": "opam2json", + "rev": "819d291ea95e271b0e6027679de6abb4d4f7f680", + "type": "github" + }, + "original": { + "owner": "tweag", + "repo": "opam2json", + "type": "github" + } + }, "root": { "inputs": { "describe-dune": "describe-dune", "dune-nix": "dune-nix", "flake-utils": "flake-utils", "mina": "mina", - "nixpkgs": "nixpkgs_3", - "nixpkgs-mozilla": "nixpkgs-mozilla_2" + "mina-rev": "mina-rev", + "nixpkgs": "nixpkgs_5", + "nixpkgs-mozilla": "nixpkgs-mozilla_3" } }, "systems": { @@ -597,6 +1059,24 @@ "repo": "flake-utils-plus", "type": "github" } + }, + "utils_2": { + "inputs": { + "flake-utils": "flake-utils_7" + }, + "locked": { + "lastModified": 1657226504, + "narHash": "sha256-GIYNjuq4mJlFgqKsZ+YrgzWm0IpA4axA3MCrdKYj7gs=", + "owner": "gytis-ivaskevicius", + "repo": "flake-utils-plus", + "rev": "2bf0f91643c2e5ae38c1b26893ac2927ac9bd82a", + "type": "github" + }, + "original": { + "owner": "gytis-ivaskevicius", + "repo": "flake-utils-plus", + "type": "github" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index dd7e4d3d42..dc525d0638 100644 --- a/flake.nix +++ b/flake.nix @@ -3,6 +3,10 @@ inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixos-23.11-small"; mina.url = "path:src/mina"; + # Nix doesn't seem to handle recursive submodules well + # so we import mina once not as a git repo so the submodules work + # but also as a git repo so the git rev is visible + mina-rev.url = "git+file:src/mina"; nixpkgs-mozilla.url = "github:mozilla/nixpkgs-mozilla"; nixpkgs-mozilla.flake = false; describe-dune.url = "github:o1-labs/describe-dune"; @@ -84,6 +88,42 @@ { targets = ["wasm32-unknown-unknown" "x86_64-unknown-linux-gnu" ]; extensions = [ "rust-src" ]; }); + rust-platform = pkgs.makeRustPlatform + { cargo = rust-channel; + rustc = rust-channel; + }; + + bindings-pkgs = with pkgs; + [ nodejs + nodePackages.npm + typescript + nodePackages.typescript-language-server + + #Rustup doesn't allow local toolchains to contain 'nightly' in the name + #so the toolchain is linked with the name nix and rustup is wrapped in a shellscript + #which calls the nix toolchain instead of the nightly one + (writeShellApplication + { name = "rustup"; + text = + '' + if [ "$1" = run ] && { [ "$2" = nightly-2023-09-01 ] || [ "$2" = 1.72-x86_64-unknowl-linux-gnu ]; } + then + echo USING NIX TOOLCHAIN + ${rustup}/bin/rustup run nix "''${@:3}" + else + echo escape rustup "$@" + ${rustup}/bin/rustup "$@" + fi + ''; + } + ) + rustup + wasm-pack + binaryen # provides wasm-opt + + dune_3 + ] ++ commonOverrides.buildInputs ; + inherit (nixpkgs) lib; # All the submodules required by .gitmodules submodules = map builtins.head (builtins.filter lib.isList @@ -111,6 +151,47 @@ command "nix-shell" }. ''; + + o1js-npm-deps = pkgs.buildNpmPackage + { name = "o1js"; + src = with pkgs.lib.fileset; + (toSource { + root = ./.; + fileset = unions [ + ./package.json + ./package-lock.json + ]; + }); + npmDepsHash = "sha256-UdzSaZJmr5k4voyKPA+9Odb6a2Ia9+3C5YQol9dSIDE="; + # The prepack script runs the build script, which we'd rather do in the build phase. + npmPackFlags = [ "--ignore-scripts" ]; + dontNpmBuild = true; + installPhase = '' + runHook preInstall + + mkdir -p $out/lib + cp -r node_modules $out/lib + + runHook postInstall + ''; + }; + test-vectors = rust-platform.buildRustPackage { + src = pkgs.lib.sourceByRegex ./src/mina/src + [ + "^lib(/crypto(/kimchi_bindings(/stubs(/.*)?)?)?)?$" + "^lib(/crypto(/proof-systems(/.*)?)?)?$" + ]; + sourceRoot = "source/lib/crypto/proof-systems/poseidon/export_test_vectors"; + patchPhase = + '' + cp ${./src/mina/src/lib/crypto/proof-systems/Cargo.lock} . + ''; + name = "export_test_vectors"; + version = "0.1.0"; + cargoSha256 = ""; + CARGO_TARGET_DIR = "./target"; + cargoLock = { lockFile = ./src/mina/src/lib/crypto/proof-systems/Cargo.lock ; }; + }; in { formatter = pkgs.nixfmt; inherit mina; @@ -124,48 +205,62 @@ export RUSTUP_HOME rustup toolchain link nix ${rust-channel} ''; - packages = with pkgs; - [ nodejs - nodePackages.npm - typescript - nodePackages.typescript-language-server + packages = bindings-pkgs; + }); - #Rustup doesn't allow local toolchains to contain 'nightly' in the name - #so the toolchain is linked with the name nix and rustup is wrapped in a shellscript - #which calls the nix toolchain instead of the nightly one - (writeShellApplication - { name = "rustup"; - text = - '' - if [ "$1" = run ] && [ "$2" = nightly-2023-09-01 ] - then - ${rustup}/bin/rustup run nix "''${@:3}" - else - ${rustup}/bin/rustup "$@" - fi - ''; - } - ) - rustup - wasm-pack - binaryen # provides wasm-opt - dune_3 - ] ++ commonOverrides.buildInputs ; - }); }; # TODO build from ./ocaml root, not ./. (after fixing a bug in dune-nix) packages = { - kim = pkgs.kimchi-rust-wasm; inherit dune-description; - bindings = prj.pkgs.o1js_bindings; + o1js-bindings = pkgs.stdenv.mkDerivation { + name = "o1js_bindings"; + src = ./.; + inherit (inputs.mina.devShells."${system}".default) + PLONK_WASM_NODEJS + PLONK_WASM_WEB + MARLIN_PLONK_STUBS + ; + PREBUILT_KIMCHI_BINDINGS_JS_WEB = + "${mina.files.src-lib-crypto-kimchi_bindings-js-web}/src/lib/crypto/kimchi_bindings/js/web"; + PREBUILT_KIMCHI_BINDINGS_JS_NODE_JS = + "${mina.files.src-lib-crypto-kimchi_bindings-js-node_js}/src/lib/crypto/kimchi_bindings/js/node_js"; + EXPORT_TEST_VECTORS = "${test-vectors}/bin/export_test_vectors"; + buildInputs = bindings-pkgs ++ [ pkgs.bash ]; + MINA_COMMIT = inputs.mina-rev.rev; + patchPhase = '' + patchShebangs ./src/bindings/scripts/ + patchShebangs ./src/bindings/crypto/test-vectors/ + ''; + buildPhase = + '' + RUSTUP_HOME=$(pwd)/.rustup + export RUSTUP_HOME + rustup toolchain link nix ${rust-channel} + cp -r ${o1js-npm-deps}/lib/node_modules/ . + + npm run build:update-bindings + mkdir $out + pushd ./src/bindings + cp -Lr ./compiled ./mina-transaction ./ocaml MINA_COMMIT $out + popd + ''; + }; + kimchi = pkgs.kimchi-rust-wasm; ocaml-js = prj.pkgs.__ocaml-js__; - default = pkgs.buildNpmPackage - { name = "o1js"; - src = ./.; - npmDepsHash = "sha256-++MTGDUVBccYN8LA2Xb0FkbrZ14ZyVCrDPESXa52AwQ="; - # TODO ideally re-build bindings here - }; + }; + apps = { + + update-bindings = { + type = "app"; + program = "${pkgs.writeShellApplication + { name = "update-bindings"; + text = + '' + cp -r ${self.packages."${system}".o1js-bindings}/* ./src/bindings + ''; + }}/bin/update-bindings"; + }; }; }); } diff --git a/src/bindings b/src/bindings index 2634cc0b11..1f81c1f691 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit 2634cc0b113e02ffc692828568ed2fe4c6c65b6a +Subproject commit 1f81c1f6912d73bbd2b39ea44c41d10222496686 From b41ba14117f444a8bd9a7a3f16aa0ca9033adb52 Mon Sep 17 00:00:00 2001 From: Youtpout Date: Fri, 22 Nov 2024 11:58:29 +0100 Subject: [PATCH 164/328] add enforceTransactionLimits parameter for network --- src/lib/mina/mina.ts | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/lib/mina/mina.ts b/src/lib/mina/mina.ts index 2dc41d5422..339e6e2717 100644 --- a/src/lib/mina/mina.ts +++ b/src/lib/mina/mina.ts @@ -104,21 +104,24 @@ function Network(options: { mina: string | string[]; archive?: string | string[]; lightnetAccountManager?: string; + enforceTransactionLimits?: boolean; }): Mina; function Network( options: | { - networkId?: NetworkId; - mina: string | string[]; - archive?: string | string[]; - lightnetAccountManager?: string; - } + networkId?: NetworkId; + mina: string | string[]; + archive?: string | string[]; + lightnetAccountManager?: string; + enforceTransactionLimits?: boolean; + } | string ): Mina { let minaNetworkId: NetworkId = 'testnet'; let minaGraphqlEndpoint: string; let archiveEndpoint: string; let lightnetAccountManagerEndpoint: string; + let enforceTransactionLimits: boolean = true; if (options && typeof options === 'string') { minaGraphqlEndpoint = options; @@ -158,6 +161,10 @@ function Network( lightnetAccountManagerEndpoint = options.lightnetAccountManager; Fetch.setLightnetAccountManagerEndpoint(lightnetAccountManagerEndpoint); } + + if (options.enforceTransactionLimits) { + enforceTransactionLimits = options.enforceTransactionLimits; + } } else { throw new Error( "Network: malformed input. Please provide a string or an object with 'mina' and 'archive' endpoints." @@ -251,7 +258,7 @@ function Network( }, sendTransaction(txn) { return toPendingTransactionPromise(async () => { - verifyTransactionLimits(txn.transaction); + if (enforceTransactionLimits) verifyTransactionLimits(txn.transaction); let [response, error] = await Fetch.sendZkapp(txn.toJSON()); let errors: string[] = []; From e22f96b3a9b2ae760cbe8c8e31ffb34a9900aa2e Mon Sep 17 00:00:00 2001 From: Florian Date: Sat, 23 Nov 2024 16:03:14 +0700 Subject: [PATCH 165/328] add compilation test --- src/lib/proof-system/zkprogram.unit-test.ts | 33 +++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/lib/proof-system/zkprogram.unit-test.ts diff --git a/src/lib/proof-system/zkprogram.unit-test.ts b/src/lib/proof-system/zkprogram.unit-test.ts new file mode 100644 index 0000000000..0b36bef28f --- /dev/null +++ b/src/lib/proof-system/zkprogram.unit-test.ts @@ -0,0 +1,33 @@ +import { Field } from '../provable/wrapped.js'; +import { ZkProgram } from './zkprogram.js'; + +const methodCount = 30; + +let MyProgram = ZkProgram({ + name: 'large-program', + publicOutput: Field, + methods: nMethods(methodCount), +}); + +function nMethods(i: number) { + let methods: Record = {}; + for (let j = 0; j < i; j++) { + methods['method' + j] = { + privateInputs: [Field], + async method(a: Field) { + return { + publicOutput: a.mul(1), + }; + }, + }; + } + return methods; +} + +try { + await MyProgram.compile(); +} catch (error) { + throw Error( + `Could not compile zkProgram with ${methodCount} branches: ${error}` + ); +} From 9e7ca4ff1c4677ee57af4a3e4b530c542821145b Mon Sep 17 00:00:00 2001 From: Florian Date: Sat, 23 Nov 2024 16:06:44 +0700 Subject: [PATCH 166/328] bindings --- src/bindings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bindings b/src/bindings index 2c62a9a755..34a05bc888 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit 2c62a9a755f1b128f89cc2131814df7157f68109 +Subproject commit 34a05bc8888eb577aa73852dab5df90c7cae1050 From fc9a389c04e401a3409a7eec5012124fcf226b61 Mon Sep 17 00:00:00 2001 From: Florian Date: Sat, 23 Nov 2024 16:07:04 +0700 Subject: [PATCH 167/328] changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index da97589a32..3862a9083a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,10 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ## [Unreleased](https://github.com/o1-labs/o1js/compare/e1bac02...HEAD) +### Added + +- Increased maximum supported amount of methods in a `SmartContract` or `ZkProgram` to 30. https://github.com/o1-labs/o1js/pull/1918 + ### Fixed - Compiling stuck in the browser for recursive zkprograms https://github.com/o1-labs/o1js/pull/1906 From 0fee0090d1a1d8d50b2290c76fc22dc87de5eedb Mon Sep 17 00:00:00 2001 From: youtpout Date: Mon, 25 Nov 2024 11:14:49 +0100 Subject: [PATCH 168/328] add test transaction --- src/lib/mina/transaction.test.ts | 215 +++++++++++++++++++++++++++++++ 1 file changed, 215 insertions(+) create mode 100644 src/lib/mina/transaction.test.ts diff --git a/src/lib/mina/transaction.test.ts b/src/lib/mina/transaction.test.ts new file mode 100644 index 0000000000..4e95bdbbcc --- /dev/null +++ b/src/lib/mina/transaction.test.ts @@ -0,0 +1,215 @@ +import { + State, + state, + UInt64, + Bool, + SmartContract, + Mina, + AccountUpdate, + method, + PublicKey, + Permissions, + VerificationKey, + Field, + Int64, + TokenId, + TokenContract as TokenContractBase, + AccountUpdateForest, + PrivateKey, +} from 'o1js'; + + + +const defaultNetwork = Mina.Network({ + networkId: "testnet", + mina: "https://example.com/graphql", + archive: "https://example.com//graphql" +}); + +const enforcedNetwork = Mina.Network({ + networkId: "testnet", + mina: "https://example.com/graphql", + archive: "https://example.com//graphql", + enforceTransactionLimits: true +}); + +const unlimitedNetwork = Mina.Network({ + networkId: "testnet", + mina: "https://unlimited.com/graphql", + archive: "https://unlimited.com//graphql", + enforceTransactionLimits: false +}); + +describe('Test default network', () => { + let bobAccount: PublicKey, + bobKey: PrivateKey; + + beforeAll(async () => { + + Mina.setActiveInstance(defaultNetwork); + bobKey = PrivateKey.random(); + bobAccount = bobKey.toPublicKey(); + }); + + + it('Simple account update', async () => { + + let txn = await Mina.transaction(async () => { + const accountUpdateBob = AccountUpdate.create(bobAccount, Field.from(1)); + accountUpdateBob.account.balance.requireEquals(UInt64.zero); + accountUpdateBob.balance.addInPlace(UInt64.one); + }); + console.log("Simple account update", txn.toPretty()); + console.log("Simple account update", txn.transaction.accountUpdates.length); + await txn.prove(); + await txn.sign([bobKey]).safeSend(); + + }); + + it('Multiple account update', async () => { + + let txn = await Mina.transaction(async () => { + for (let index = 0; index < 2; index++) { + const accountUpdateBob = AccountUpdate.create(bobAccount, Field.from(index)); + accountUpdateBob.account.balance.requireEquals(UInt64.zero); + accountUpdateBob.balance.addInPlace(UInt64.one); + } + }); + console.log("Multiple account update", txn.toPretty()); + console.log("Multiple account update", txn.transaction.accountUpdates.length); + await txn.prove(); + await txn.sign([bobKey]).safeSend(); + + }); + + it('More than limit account update', async () => { + + let txn = await Mina.transaction(async () => { + for (let index = 0; index < 12; index++) { + const accountUpdateBob = AccountUpdate.create(bobAccount, Field.from(index)); + accountUpdateBob.account.balance.requireEquals(UInt64.zero); + accountUpdateBob.balance.addInPlace(UInt64.one); + } + }); + console.log("More than limit account update", txn.toPretty()); + console.log("More than limit account update", txn.transaction.accountUpdates.length); + await txn.prove(); + await expect(txn.sign([bobKey]).safeSend()).rejects.toThrow(); + }); +}); + +describe('Test enforced network', () => { + let bobAccount: PublicKey, + bobKey: PrivateKey; + + beforeAll(async () => { + + Mina.setActiveInstance(enforcedNetwork); + bobKey = PrivateKey.random(); + bobAccount = bobKey.toPublicKey(); + }); + + + it('Simple account update', async () => { + + let txn = await Mina.transaction(async () => { + const accountUpdateBob = AccountUpdate.create(bobAccount, Field.from(1)); + accountUpdateBob.account.balance.requireEquals(UInt64.zero); + accountUpdateBob.balance.addInPlace(UInt64.one); + }); + console.log("Simple account update", txn.toPretty()); + console.log("Simple account update", txn.transaction.accountUpdates.length); + await txn.prove(); + await txn.sign([bobKey]).safeSend(); + + }); + + it('Multiple account update', async () => { + + let txn = await Mina.transaction(async () => { + for (let index = 0; index < 2; index++) { + const accountUpdateBob = AccountUpdate.create(bobAccount, Field.from(index)); + accountUpdateBob.account.balance.requireEquals(UInt64.zero); + accountUpdateBob.balance.addInPlace(UInt64.one); + } + }); + console.log("Multiple account update", txn.toPretty()); + console.log("Multiple account update", txn.transaction.accountUpdates.length); + await txn.prove(); + await txn.sign([bobKey]).safeSend(); + + }); + + it('More than limit account update', async () => { + + let txn = await Mina.transaction(async () => { + for (let index = 0; index < 12; index++) { + const accountUpdateBob = AccountUpdate.create(bobAccount, Field.from(index)); + accountUpdateBob.account.balance.requireEquals(UInt64.zero); + accountUpdateBob.balance.addInPlace(UInt64.one); + } + }); + console.log("More than limit account update", txn.toPretty()); + console.log("More than limit account update", txn.transaction.accountUpdates.length); + await txn.prove(); + await expect(txn.sign([bobKey]).safeSend()).rejects.toThrow(); + }); +}); + +describe('Test unlimited network', () => { + let bobAccount: PublicKey, + bobKey: PrivateKey; + + beforeAll(async () => { + + Mina.setActiveInstance(unlimitedNetwork); + bobKey = PrivateKey.random(); + bobAccount = bobKey.toPublicKey(); + }); + + + it('Simple account update', async () => { + + let txn = await Mina.transaction(async () => { + const accountUpdateBob = AccountUpdate.create(bobAccount, Field.from(1)); + accountUpdateBob.account.balance.requireEquals(UInt64.zero); + accountUpdateBob.balance.addInPlace(UInt64.one); + }); + console.log("Simple account update", txn.toPretty()); + console.log("Simple account update", txn.transaction.accountUpdates.length); + await txn.prove(); + await txn.sign([bobKey]).safeSend(); + + }); + + it('Multiple account update', async () => { + + let txn = await Mina.transaction(async () => { + for (let index = 0; index < 2; index++) { + const accountUpdateBob = AccountUpdate.create(bobAccount, Field.from(index)); + accountUpdateBob.account.balance.requireEquals(UInt64.zero); + accountUpdateBob.balance.addInPlace(UInt64.one); + } + }); + console.log("Multiple account update", txn.toPretty()); + console.log("Multiple account update", txn.transaction.accountUpdates.length); + await txn.prove(); + await txn.sign([bobKey]).safeSend(); + + }); + + it('More than limit account update', async () => { + + let txn = await Mina.transaction(async () => { + for (let index = 0; index < 12; index++) { + const accountUpdateBob = AccountUpdate.create(bobAccount, Field.from(index)); + accountUpdateBob.account.balance.requireEquals(UInt64.zero); + accountUpdateBob.balance.addInPlace(UInt64.one); + } + }); + console.log("More than limit account update", txn.toPretty()); + console.log("More than limit account update", txn.transaction.accountUpdates.length); + await txn.prove(); + await txn.sign([bobKey]).safeSend(); + }); +}); \ No newline at end of file From c4a87698b8addda1aa75cb995da31b8fb889a4cd Mon Sep 17 00:00:00 2001 From: querolita Date: Mon, 25 Nov 2024 12:12:18 +0100 Subject: [PATCH 169/328] first version of nix readme --- README-dev.md | 4 +- README-nix.md | 193 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 195 insertions(+), 2 deletions(-) create mode 100644 README-nix.md diff --git a/README-dev.md b/README-dev.md index 7d8e1c8f59..8d1ec0fbbc 100644 --- a/README-dev.md +++ b/README-dev.md @@ -15,8 +15,8 @@ Before starting, ensure you have the following tools installed: - [Git](https://git-scm.com/) - [Node.js and npm](https://nodejs.org/) -- [Dune](https://github.com/ocaml/dune) (only needed when compiling o1js from source) -- [Cargo](https://www.rust-lang.org/learn/get-started) (only needed when compiling o1js from source) +- [Dune, ocamlc, opam](https://github.com/ocaml/dune) (only needed when compiling o1js from source) +- [Cargo, rustup](https://www.rust-lang.org/learn/get-started) (only needed when compiling o1js from source) After cloning the repository, you need to fetch the submodules: diff --git a/README-nix.md b/README-nix.md new file mode 100644 index 0000000000..3737a78553 --- /dev/null +++ b/README-nix.md @@ -0,0 +1,193 @@ +# o1js README-nix + +[Nix](https://nixos.org/) is a tool for package management and system +configurationthat can help developers build a project in a reproducible and +reliable manner, without messing up versions during upgrades. + +Much like the `mina` repository, you can use Nix to +handle the dependencies required across the codebase, including npm scripts. + +> **When should I use Nix?** +> If you cannot build the codebase locally (due to untrusty package manager, +> faulty versioning, or unavailable libraries), it is a good idea to try the Nix +> build instead. This can specially happen if you're using a Mac–and even more +> likely–with non-Intel chips. + +## Installing Nix + +The following command will install Nix on your machine. + +```console +sh <(curl -L https://nixos.org/nix/install) --daemon +``` + +If you're unsure about your Nix setup, the assistant will guide you towards a +clean installation. It will involve backing up your old `/etc/X` and `/etc/X.backup-before-nix` for `X = {bashrc, zshrc}`, and finally uninstalling and +reinstalling Nix from scratch. + +> **warning for macOS users**: macOS updates will often break your nix +> installation. To prevent that, you can add the following to your `~/.bashrc` +> or `~/.zshrc`: +> +> ```bash +> # avoid macOS updates to destroy nix +> if [ -e '/nix/var/nix/profiles/default/etc/profile.d/>nix-daemon.sh' ]; then +> source '/nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh' +> fi +> ``` + +After installing, the current shell won't be a Nix shell. To create one, open a +new shell and type + +```console +nix-shell -p nix-info --run "nix-info -m" +``` + +That should output some basic information about the configuration parameters for Nix. + +## Building with Nix + +From a new shell, go to `{REPO_PATH}/o1js` and from there execute `./pin.sh` to +update the submodules and add the flakes entries. Then, you can open a Nix shell +with all the dependencies required executing `nix develop o1js#default`, or +alternatively `nix develop o1js#mina-shell` (which works better from MacOS). Once + +```console +cd {REPO_PATH}/o1js +./pin.sh +nix develop o1js#default +``` + +You will observe that the current devshell becomes a Nix shell with the right +configuration for `o1js` and `mina`. + +Then, you can build o1js and update the bindings. + +```console +npm run build +npm run build:update-bindings +``` + +If you need to update the underlying `mina` code, you can also do so with Nix, +but from the corresopnding subdirectory. + +## Common errors + +Errors while using Nix have been reported. This section collects a set of common +errors and proposes fixes for them. + +### Compiling _export_test_vectors_ + +When trying to update the bindings for o1js in MacOS, Nix might fail at +compiling the `export_test_vectors` with the following error log: + +```console +error: linking with `cc` failed: exit status: 1 + = note: ld: library not found for -liconv + collect2: error: ld returned 1 exit status + +error: could not compile `export_test_vectors` (bin "export_test_vectors") due to previous error +``` + +That is because this library is not symlinked into `/opt/homebrew` since macOS +already provides this software and installing another version could cause +problems. + +#### Fix for MacOS + +Install `libiconv` with + +```console +brew install libiconv +``` + +and update your `~/.zshrc` with the following lines + +```bash +# libiconv config +export PATH="/opt/homebrew/opt/libiconv/bin:$PATH" +export LDFLAGS="-L/opt/homebrew/opt/libiconv/lib" +export CPPFLAGS="-I/opt/homebrew/opt/libiconv/include" +export LIBRARY_PATH="/opt/homebrew/opt/libiconv/lib:$LIBRARY_PATH" +``` + +### wasm32-unknown-unknown + +The rust compiler and/or Wasm-pack might not be correctly setup in the Nix shell. + +```console +Error: wasm32-unknown-unknown target not found in sysroot: "/nix/store/w30zw23kmgks77d870i502a3185hjycv-rust" + +Used rustc from the following path: "/nix/store/wcm8caqd6g7bcbddpyxan1jzj3apkmxy-rustup-1.26.0/bin/rustc" +It looks like Rustup is not being used. For non-Rustup setups, the wasm32-unknown-unknown target needs to be installed manually. See https://rustwasm.github.io/wasm-pack/book/prerequisites/non-rustup-setups.html on how to do this. + +Caused by: wasm32-unknown-unknown target not found in sysroot: "/nix/store/w30zw23kmgks77d870i502a3185hjycv-rust" +``` + +#### Fix + +This is caused because the Rust compiler in Nix does not have access to the +corresponding `wasm32-unknown-unknown` target. Let `{RUSTDIR}` be the directory +of the Rust location inside Nix, as shown in the error code; e.g. +`/nix/store/wcm8caqd6g7bcbddpyxan1jzj3apkmxy-rustup-1.26.0/bin`, then you can +check the version of the compiler used by typing: + +```bash +{RUSTDIR}/rustc --version +``` + +Which will reply with something like + +```bash +rustc 1.82.0 (f6e511eec 2024-10-15) +``` + +Then the Wasm target can be automatically installed using + +```console +{RUSTDIR}/rustup target add wasm32-unknown-unknown +``` + +Alternatively, this can be done manually downloading the right version of the +target with + +```console +wget https://static.rust-lang.org/dist/rust-std-x.xx.x-wasm32-unknown-unknown.tar.gz +``` + +where _`x.xx.x`_ corresponds to the version of `rustc` (in the example, 1.82.0). +Once unpacked, you should see a similar structure: + +```console +rust-std-1.82.0-wasm32-unknown-unknown +├── components +├── install.sh +├── rust-installer-version +└── rust-std-wasm32-unknown-unknown + ├── lib + │   └── rustlib + │   └── wasm32-unknown-unknown +``` + +Finally, the `wasm32-unknown-unknown` folder must be moved into the +`./lib/rustlib/` directory in the sysroot like so: + +Let `{SYSROOT}` be the directory of the Rust in Nix shown in the error code; +e.g. `/nix/store/w30zw23kmgks77d870i502a3185hjycv-rust`, then the Wasm target +can be automatically installed downloading it from + +```bash +mv rust-std-1.82.0-wasm32-unknown-unknown/rust-std-wasm32-unknown-unknown/lib/rustlib/wasm32-unknown-unknown {SYSROOT}/lib/rustlib/wasm32-unknown-unknown/ +``` + +### Cargo not found + +```console +error: "/nix/store/w30zw23kmgks77d870i502a3185hjycv-rust/lib/rustlib/src/rust/Cargo.lock" + does not exist, unable to build with the standard library, try: + rustup component add rust-src --toolchain nix +``` + +#### Fix + +Install `cargo` on your host machine. From cc64367e7c5ac188e9cc9428725f6622c845b8c4 Mon Sep 17 00:00:00 2001 From: querolita Date: Mon, 25 Nov 2024 12:36:35 +0100 Subject: [PATCH 170/328] flakes paragraph --- README-nix.md | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/README-nix.md b/README-nix.md index 3737a78553..9f9d7fcc91 100644 --- a/README-nix.md +++ b/README-nix.md @@ -45,12 +45,31 @@ nix-shell -p nix-info --run "nix-info -m" That should output some basic information about the configuration parameters for Nix. +## Enabling Flakes (recommended) + +Mina is packaged using [Nix Flakes](https://nixos.wiki/wiki/Flakes), +which are an experimental feature of Nix. However, compatibility with +pre-flake Nix is provided. If you wish to contribute the Nix +expressions in this repository, or want to get some convenience +features and speed improvements, **it is advisable to enable flakes**. For +this, you'll want to make sure you're running recent Nix (⩾2.5) and +have enabled the relevant experimental features, either in +`/etc/nix/nix.conf` or (recommended) in `~/.config/nix/nix.conf`: + +``` +mkdir -p "${XDG_CONFIG_HOME-${HOME}/.config}/nix" +echo 'experimental-features = nix-command flakes' > "${XDG_CONFIG_HOME-${HOME}/.config}/nix/nix.conf" +``` + +You can check that your flake support is working by running `nix flake metadata +github:nixos/nixpkgs` for example. + ## Building with Nix From a new shell, go to `{REPO_PATH}/o1js` and from there execute `./pin.sh` to update the submodules and add the flakes entries. Then, you can open a Nix shell with all the dependencies required executing `nix develop o1js#default`, or -alternatively `nix develop o1js#mina-shell` (which works better from MacOS). Once +alternatively `nix develop o1js#mina-shell` (which works better from MacOS). ```console cd {REPO_PATH}/o1js From 3b4361481a47cd482adc0571ed694c9f9b6def13 Mon Sep 17 00:00:00 2001 From: youtpout Date: Mon, 25 Nov 2024 15:26:36 +0100 Subject: [PATCH 171/328] update enforce variable verification --- src/lib/mina/mina.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lib/mina/mina.ts b/src/lib/mina/mina.ts index 339e6e2717..aba1599b2c 100644 --- a/src/lib/mina/mina.ts +++ b/src/lib/mina/mina.ts @@ -162,7 +162,8 @@ function Network( Fetch.setLightnetAccountManagerEndpoint(lightnetAccountManagerEndpoint); } - if (options.enforceTransactionLimits) { + if (options.enforceTransactionLimits !== undefined && + typeof options.enforceTransactionLimits === 'boolean') { enforceTransactionLimits = options.enforceTransactionLimits; } } else { From b6e9023d6f4e891fdc31593d2b9edf983de68f53 Mon Sep 17 00:00:00 2001 From: youtpout Date: Mon, 25 Nov 2024 16:00:22 +0100 Subject: [PATCH 172/328] remove console log from tests --- src/lib/mina/transaction.test.ts | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/src/lib/mina/transaction.test.ts b/src/lib/mina/transaction.test.ts index 4e95bdbbcc..580e2afa5e 100644 --- a/src/lib/mina/transaction.test.ts +++ b/src/lib/mina/transaction.test.ts @@ -59,8 +59,6 @@ describe('Test default network', () => { accountUpdateBob.account.balance.requireEquals(UInt64.zero); accountUpdateBob.balance.addInPlace(UInt64.one); }); - console.log("Simple account update", txn.toPretty()); - console.log("Simple account update", txn.transaction.accountUpdates.length); await txn.prove(); await txn.sign([bobKey]).safeSend(); @@ -75,8 +73,6 @@ describe('Test default network', () => { accountUpdateBob.balance.addInPlace(UInt64.one); } }); - console.log("Multiple account update", txn.toPretty()); - console.log("Multiple account update", txn.transaction.accountUpdates.length); await txn.prove(); await txn.sign([bobKey]).safeSend(); @@ -91,9 +87,8 @@ describe('Test default network', () => { accountUpdateBob.balance.addInPlace(UInt64.one); } }); - console.log("More than limit account update", txn.toPretty()); - console.log("More than limit account update", txn.transaction.accountUpdates.length); await txn.prove(); + // failure with default enforceTransactionLimits await expect(txn.sign([bobKey]).safeSend()).rejects.toThrow(); }); }); @@ -117,8 +112,6 @@ describe('Test enforced network', () => { accountUpdateBob.account.balance.requireEquals(UInt64.zero); accountUpdateBob.balance.addInPlace(UInt64.one); }); - console.log("Simple account update", txn.toPretty()); - console.log("Simple account update", txn.transaction.accountUpdates.length); await txn.prove(); await txn.sign([bobKey]).safeSend(); @@ -133,8 +126,6 @@ describe('Test enforced network', () => { accountUpdateBob.balance.addInPlace(UInt64.one); } }); - console.log("Multiple account update", txn.toPretty()); - console.log("Multiple account update", txn.transaction.accountUpdates.length); await txn.prove(); await txn.sign([bobKey]).safeSend(); @@ -149,9 +140,8 @@ describe('Test enforced network', () => { accountUpdateBob.balance.addInPlace(UInt64.one); } }); - console.log("More than limit account update", txn.toPretty()); - console.log("More than limit account update", txn.transaction.accountUpdates.length); await txn.prove(); + // failure with enforceTransactionLimits = true await expect(txn.sign([bobKey]).safeSend()).rejects.toThrow(); }); }); @@ -175,8 +165,6 @@ describe('Test unlimited network', () => { accountUpdateBob.account.balance.requireEquals(UInt64.zero); accountUpdateBob.balance.addInPlace(UInt64.one); }); - console.log("Simple account update", txn.toPretty()); - console.log("Simple account update", txn.transaction.accountUpdates.length); await txn.prove(); await txn.sign([bobKey]).safeSend(); @@ -191,8 +179,6 @@ describe('Test unlimited network', () => { accountUpdateBob.balance.addInPlace(UInt64.one); } }); - console.log("Multiple account update", txn.toPretty()); - console.log("Multiple account update", txn.transaction.accountUpdates.length); await txn.prove(); await txn.sign([bobKey]).safeSend(); @@ -207,9 +193,8 @@ describe('Test unlimited network', () => { accountUpdateBob.balance.addInPlace(UInt64.one); } }); - console.log("More than limit account update", txn.toPretty()); - console.log("More than limit account update", txn.transaction.accountUpdates.length); await txn.prove(); + // success with enforceTransactionLimits = false await txn.sign([bobKey]).safeSend(); }); }); \ No newline at end of file From 0aec72bcf69d47c1f3d4e25c821379b22a3c0357 Mon Sep 17 00:00:00 2001 From: youtpout Date: Mon, 25 Nov 2024 16:28:42 +0100 Subject: [PATCH 173/328] update changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index da97589a32..e5e1272dd2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,11 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ## [Unreleased](https://github.com/o1-labs/o1js/compare/e1bac02...HEAD) + +### Added + +- Add `enforceTransactionLimits` parameter on Network https://github.com/o1-labs/o1js/issues/1910 + ### Fixed - Compiling stuck in the browser for recursive zkprograms https://github.com/o1-labs/o1js/pull/1906 From b2d62a4a38cd44e61b8435991ae31733a9d8c4f4 Mon Sep 17 00:00:00 2001 From: querolita Date: Mon, 25 Nov 2024 16:47:25 +0100 Subject: [PATCH 174/328] fixed typo in rangeCheck16 error message --- src/lib/provable/gadgets/range-check.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/provable/gadgets/range-check.ts b/src/lib/provable/gadgets/range-check.ts index da661c5def..f65c90e4db 100644 --- a/src/lib/provable/gadgets/range-check.ts +++ b/src/lib/provable/gadgets/range-check.ts @@ -332,7 +332,7 @@ function rangeCheck16(x: Field) { if (x.isConstant()) { assert( x.toBigInt() < 1n << 16n, - `rangeCheck16: expected field to fit in 8 bits, got ${x}` + `rangeCheck16: expected field to fit in 16 bits, got ${x}` ); return; } From 2065ac67e73f2ca2362f8b0a8cc1e3db796b38d3 Mon Sep 17 00:00:00 2001 From: querolita Date: Mon, 25 Nov 2024 16:53:23 +0100 Subject: [PATCH 175/328] add pad and zip for arrays, improve chunk error message --- src/lib/util/arrays.ts | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/lib/util/arrays.ts b/src/lib/util/arrays.ts index 891de81015..d282ba607e 100644 --- a/src/lib/util/arrays.ts +++ b/src/lib/util/arrays.ts @@ -1,9 +1,12 @@ import { assert } from './errors.js'; -export { chunk, chunkString }; +export { chunk, chunkString, zip, pad }; function chunk(array: T[], size: number): T[][] { - assert(array.length % size === 0, 'invalid input length'); + assert( + array.length % size === 0, + 'chunk(): invalid input length, it must be a multiple of ${size}' + ); return Array.from({ length: array.length / size }, (_, i) => array.slice(size * i, size * (i + 1)) ); @@ -12,3 +15,16 @@ function chunk(array: T[], size: number): T[][] { function chunkString(str: string, size: number): string[] { return chunk([...str], size).map((c) => c.join('')); } + +function zip(a: T[], b: S[]) { + assert(a.length === b.length, 'zip(): arrays of unequal length'); + return a.map((a, i): [T, S] => [a, b[i]!]); +} + +function pad(array: T[], size: number, value: T): T[] { + assert( + array.length <= size, + `target size ${size} should be greater or equal than the length of the array ${array.length}` + ); + return array.concat(Array.from({ length: size - array.length }, () => value)); +} From 9375393b1e5e64e0652c4d1de97914d2e2a043d3 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Mon, 25 Nov 2024 23:56:37 +0800 Subject: [PATCH 176/328] Revert "chore(bindings): update subproject commit reference to e172bf02e to track latest changes" This reverts commit fee51bc2b0fee198ea6ffcded5b40ad5511af70e. --- src/bindings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bindings b/src/bindings index e172bf02e7..015333ff22 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit e172bf02e79ce8993c6dbac06b238822313a7441 +Subproject commit 015333ff220ed723f12580acfd6a6beab593072f From 1da031ae6e470fe169fa225455bec52ce1d87c03 Mon Sep 17 00:00:00 2001 From: querolita Date: Mon, 25 Nov 2024 16:57:34 +0100 Subject: [PATCH 177/328] update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index da97589a32..348b2a3fee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,8 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Support secp256r1 in elliptic curve and ECDSA gadgets https://github.com/o1-labs/o1js/pull/1885 +- Provide `zip` and `pad` for the array utility https://github.com/o1-labs/o1js/pull/1921 + ### Fixed - Witness generation error in `Gadgets.arrayGet()` when accessing out-of-bounds indices https://github.com/o1-labs/o1js/pull/1886 From 240c96a76d4ac0dab14530cb6265db2e1fb68c41 Mon Sep 17 00:00:00 2001 From: querolita Date: Mon, 25 Nov 2024 16:59:01 +0100 Subject: [PATCH 178/328] update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index da97589a32..48876c95f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,8 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Compiling stuck in the browser for recursive zkprograms https://github.com/o1-labs/o1js/pull/1906 +- Error message in `rangeCheck16` gadget https://github.com/o1-labs/o1js/pull/1920 + ## [2.1.0](https://github.com/o1-labs/o1js/compare/b04520d...e1bac02) - 2024-11-13 ### Added From e34353edcf107623c67539bcae5980b0e23e9115 Mon Sep 17 00:00:00 2001 From: querolita Date: Mon, 25 Nov 2024 16:59:39 +0100 Subject: [PATCH 179/328] modify changelog section --- CHANGELOG.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 348b2a3fee..fffa8f30db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,14 +21,16 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Compiling stuck in the browser for recursive zkprograms https://github.com/o1-labs/o1js/pull/1906 +### Added + +- Provide `zip` and `pad` for the array utility https://github.com/o1-labs/o1js/pull/1921 + ## [2.1.0](https://github.com/o1-labs/o1js/compare/b04520d...e1bac02) - 2024-11-13 ### Added - Support secp256r1 in elliptic curve and ECDSA gadgets https://github.com/o1-labs/o1js/pull/1885 -- Provide `zip` and `pad` for the array utility https://github.com/o1-labs/o1js/pull/1921 - ### Fixed - Witness generation error in `Gadgets.arrayGet()` when accessing out-of-bounds indices https://github.com/o1-labs/o1js/pull/1886 From fb6f43ff21a1abe85e1c983c768c3d745004315d Mon Sep 17 00:00:00 2001 From: querolita Date: Mon, 25 Nov 2024 17:01:32 +0100 Subject: [PATCH 180/328] add assertNone method for options --- src/lib/provable/option.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/lib/provable/option.ts b/src/lib/provable/option.ts index cc82a568a3..c579e2401f 100644 --- a/src/lib/provable/option.ts +++ b/src/lib/provable/option.ts @@ -9,6 +9,7 @@ export { Option, OptionOrValue }; type Option = { isSome: Bool; value: T } & { assertSome(message?: string): T; + assertNone(): void; orElse(defaultValue: T | V): T; }; @@ -104,6 +105,10 @@ function Option( return this.value; } + assertNone(): void { + this.isSome.assertFalse(); + } + static from(value?: V | T) { return value === undefined ? new Option_({ From 1adb75953033a32bf238b29fc1d2d6b883c6fcdb Mon Sep 17 00:00:00 2001 From: querolita Date: Mon, 25 Nov 2024 17:03:24 +0100 Subject: [PATCH 181/328] update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index da97589a32..d09013958c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,10 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Compiling stuck in the browser for recursive zkprograms https://github.com/o1-labs/o1js/pull/1906 +### Added + +- Method for optional types to assert none https://github.com/o1-labs/o1js/pull/1922 + ## [2.1.0](https://github.com/o1-labs/o1js/compare/b04520d...e1bac02) - 2024-11-13 ### Added From c723df4788d4cfcc65b4d4797dab84ab91ea75a7 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Tue, 26 Nov 2024 00:48:57 +0800 Subject: [PATCH 182/328] Revert "chore(mina): update subproject commit reference to 24c8b2d723fb09d0d7f996b6ac35373dc27084ef" This reverts commit b9807813602f49c7ed1539370612e5675fa61241. --- src/mina | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mina b/src/mina index 24c8b2d723..9bdaae9990 160000 --- a/src/mina +++ b/src/mina @@ -1 +1 @@ -Subproject commit 24c8b2d723fb09d0d7f996b6ac35373dc27084ef +Subproject commit 9bdaae99904c13e3e10841ec6b778e45cdacabfb From dca71567d56d015c63efdb4a690919cf062f50a5 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Tue, 26 Nov 2024 01:45:08 +0800 Subject: [PATCH 183/328] chore(CHANGELOG.md): move changelog entry to unreleased section --- CHANGELOG.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c1a09826c..0afdce7066 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,16 +17,16 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ## [Unreleased](https://github.com/o1-labs/o1js/compare/e1bac02...HEAD) +### Added + +-`ZkProgram` to support non-pure provable types as inputs and outputs https://github.com/o1-labs/o1js/pull/1828 + ### Fixed - Compiling stuck in the browser for recursive zkprograms https://github.com/o1-labs/o1js/pull/1906 ## [2.1.0](https://github.com/o1-labs/o1js/compare/b04520d...e1bac02) - 2024-11-13 -### Added - --`ZkProgram` to support non-pure provable types as inputs and outputs https://github.com/o1-labs/o1js/pull/1828 - - Support secp256r1 in elliptic curve and ECDSA gadgets https://github.com/o1-labs/o1js/pull/1885 ### Fixed From 4a9c431e09be54338aecf0e7f46715fbcd8b6a01 Mon Sep 17 00:00:00 2001 From: Geometer1729 <16kuhnb@gmail.com> Date: Mon, 25 Nov 2024 16:37:06 -0500 Subject: [PATCH 184/328] fix node_bindings --- flake.nix | 3 ++- pin.sh | 1 + src/bindings | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/flake.nix b/flake.nix index dc525d0638..514e2cd2a1 100644 --- a/flake.nix +++ b/flake.nix @@ -242,7 +242,8 @@ npm run build:update-bindings mkdir $out pushd ./src/bindings - cp -Lr ./compiled ./mina-transaction ./ocaml MINA_COMMIT $out + rm -rf ./compiled/_node_bindings + cp -Lr ./compiled ./mina-transaction ./ocaml ./MINA_COMMIT $out popd ''; }; diff --git a/pin.sh b/pin.sh index 6815dbac8e..c109f6733f 100755 --- a/pin.sh +++ b/pin.sh @@ -10,4 +10,5 @@ git submodule sync && git submodule update --init --recursive nix registry add o1js "git+file://$ROOT?submodules=1" # update mina input to local submodule nix flake update mina --override-input mina 'path:src/mina' --flake '.?submodules=1' +nix flake update mina-rev --flake '.?submodules=1' popd diff --git a/src/bindings b/src/bindings index 1f81c1f691..7b62ab3d03 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit 1f81c1f6912d73bbd2b39ea44c41d10222496686 +Subproject commit 7b62ab3d036cdd9ac6241c26f107cf05d5436125 From 05cbccf77f64be6c2a6745a9424d5c59d727d724 Mon Sep 17 00:00:00 2001 From: Geometer1729 <16kuhnb@gmail.com> Date: Mon, 25 Nov 2024 16:52:46 -0500 Subject: [PATCH 185/328] merge main in bindings --- src/bindings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bindings b/src/bindings index 7b62ab3d03..a5a5dc4ca2 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit 7b62ab3d036cdd9ac6241c26f107cf05d5436125 +Subproject commit a5a5dc4ca204285b8f088067c130f1d440f2a5b7 From d05a800703970a14c0e8c804edd49a760b42f207 Mon Sep 17 00:00:00 2001 From: Geometer1729 <16kuhnb@gmail.com> Date: Mon, 25 Nov 2024 16:54:35 -0500 Subject: [PATCH 186/328] use nix derivation in ci --- .github/workflows/build-bindings.yml | 6 +++--- flake.nix | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-bindings.yml b/.github/workflows/build-bindings.yml index 7ffc1a7cff..0f4070b492 100644 --- a/.github/workflows/build-bindings.yml +++ b/.github/workflows/build-bindings.yml @@ -1,4 +1,4 @@ -# Purpose: We want to build the o1js bindings in CI so that people in the +# Purpose: We want to build the o1js bindings in CI so that people in the # community can change them without being scared of breaking things, or # needing to do the complicated (without nix) build setup. @@ -7,7 +7,7 @@ name: Build o1js bindings on: pull_request: -jobs: +jobs: nix-build: name: build-bindings-ubuntu runs-on: [sdk-self-hosted-linux-amd64-build-system] @@ -22,4 +22,4 @@ jobs: # Until we restart the runner and the PATH gets updated from /etc/bash.bashrc export PATH="$PATH":/nix/var/nix/profiles/default/bin ./pin.sh - nix develop o1js --command bash -c "npm run build:update-bindings" + nix run o1js#update-bindings diff --git a/flake.nix b/flake.nix index 514e2cd2a1..448235d0a7 100644 --- a/flake.nix +++ b/flake.nix @@ -251,7 +251,6 @@ ocaml-js = prj.pkgs.__ocaml-js__; }; apps = { - update-bindings = { type = "app"; program = "${pkgs.writeShellApplication From f62c1b13bd2362f1359b6c6842fdd06f1c86a1bc Mon Sep 17 00:00:00 2001 From: Geometer1729 <16kuhnb@gmail.com> Date: Mon, 25 Nov 2024 18:25:29 -0500 Subject: [PATCH 187/328] update npmDepsHash --- flake.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index 448235d0a7..007158f4de 100644 --- a/flake.nix +++ b/flake.nix @@ -162,7 +162,7 @@ ./package-lock.json ]; }); - npmDepsHash = "sha256-UdzSaZJmr5k4voyKPA+9Odb6a2Ia9+3C5YQol9dSIDE="; + npmDepsHash = "sha256-8EPvXpOgn0nvm/pFKN3h6EMjabOeBqfy5optIfe8E8Q="; # The prepack script runs the build script, which we'd rather do in the build phase. npmPackFlags = [ "--ignore-scripts" ]; dontNpmBuild = true; From 538b686adec3b3d1d4821912cf57b26720c6418f Mon Sep 17 00:00:00 2001 From: Serhii Shymkiv Date: Tue, 26 Nov 2024 09:51:12 +0200 Subject: [PATCH 188/328] Cleanup Nix store after the o1js bindings build procedure. --- .github/workflows/build-bindings.yml | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-bindings.yml b/.github/workflows/build-bindings.yml index 7ffc1a7cff..b90a01a28e 100644 --- a/.github/workflows/build-bindings.yml +++ b/.github/workflows/build-bindings.yml @@ -1,4 +1,4 @@ -# Purpose: We want to build the o1js bindings in CI so that people in the +# Purpose: We want to build the o1js bindings in CI so that people in the # community can change them without being scared of breaking things, or # needing to do the complicated (without nix) build setup. @@ -7,7 +7,7 @@ name: Build o1js bindings on: pull_request: -jobs: +jobs: nix-build: name: build-bindings-ubuntu runs-on: [sdk-self-hosted-linux-amd64-build-system] @@ -17,9 +17,16 @@ jobs: - uses: actions/checkout@v4 with: submodules: recursive - - run: | + - name: Build the o1js bindings + run: | set -Eeu # Until we restart the runner and the PATH gets updated from /etc/bash.bashrc export PATH="$PATH":/nix/var/nix/profiles/default/bin ./pin.sh nix develop o1js --command bash -c "npm run build:update-bindings" + - name: Cleanup the Nix store + run: | + nix-env --delete-generations old + nix-collect-garbage -d --quiet + nix-store --gc --print-dead + nix-store --optimise From a91a75be4628c8177ac85129c9fa2c9aa9288aa1 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Tue, 26 Nov 2024 19:23:40 +0800 Subject: [PATCH 189/328] refactor(program-with-non-pure-input.ts): remove unused NonPureInputProgram to clean up code and improve readability docs(program-with-non-pure-input.ts): remove console logs related to NonPureInputProgram compilation for clarity and cleanliness --- .../zkprogram/program-with-non-pure-input.ts | 21 ------------------- 1 file changed, 21 deletions(-) diff --git a/src/examples/zkprogram/program-with-non-pure-input.ts b/src/examples/zkprogram/program-with-non-pure-input.ts index a9908d9b42..ca4355b408 100644 --- a/src/examples/zkprogram/program-with-non-pure-input.ts +++ b/src/examples/zkprogram/program-with-non-pure-input.ts @@ -40,17 +40,6 @@ let NonPureOutputProgram = ZkProgram({ }, }); -let NonPureInputProgram = ZkProgram({ - name: 'example-with-non-pure-input', - publicInput: MyStruct, - - methods: { - baseCase: { - privateInputs: [], - async method(input) {}, - }, - }, -}); console.log('compiling NonPureIOprogram...'); await NonPureIOprogram.compile(); console.log('compile done'); @@ -71,13 +60,3 @@ let isProof2Valid = await NonPureOutputProgram.verify(proof); assert(isProof2Valid, 'proof not valid!'); assert(proof.publicOutput.label === 'output'); console.log('output proof', proof); - -console.log('compiling NonPureInputProgram...'); -await NonPureInputProgram.compile(); -console.log('compile done'); - -({ proof } = await NonPureInputProgram.baseCase(input)); -let isProof3Valid = await NonPureInputProgram.verify(proof); -assert(isProof3Valid, 'proof not valid!'); -assert(proof.publicInput.label === 'input'); -console.log('input proof', proof); From 7e5fb96a4625cbf10716d06fd89ed1c65e1c44a2 Mon Sep 17 00:00:00 2001 From: youtpout Date: Tue, 26 Nov 2024 13:21:56 +0100 Subject: [PATCH 190/328] rename test, change parameter name to bypassTransactionLimits --- ...ction.test.ts => mina.network.unit-test.ts} | 18 ++++++++++-------- src/lib/mina/mina.ts | 10 +++++----- 2 files changed, 15 insertions(+), 13 deletions(-) rename src/lib/mina/{transaction.test.ts => mina.network.unit-test.ts} (93%) diff --git a/src/lib/mina/transaction.test.ts b/src/lib/mina/mina.network.unit-test.ts similarity index 93% rename from src/lib/mina/transaction.test.ts rename to src/lib/mina/mina.network.unit-test.ts index 580e2afa5e..73b2a0e1d0 100644 --- a/src/lib/mina/transaction.test.ts +++ b/src/lib/mina/mina.network.unit-test.ts @@ -17,6 +17,8 @@ import { AccountUpdateForest, PrivateKey, } from 'o1js'; +import { test, describe, it, before } from 'node:test'; +import { expect } from 'expect'; @@ -30,21 +32,21 @@ const enforcedNetwork = Mina.Network({ networkId: "testnet", mina: "https://example.com/graphql", archive: "https://example.com//graphql", - enforceTransactionLimits: true + bypassTransactionLimits: false }); const unlimitedNetwork = Mina.Network({ networkId: "testnet", mina: "https://unlimited.com/graphql", archive: "https://unlimited.com//graphql", - enforceTransactionLimits: false + bypassTransactionLimits: true }); describe('Test default network', () => { let bobAccount: PublicKey, bobKey: PrivateKey; - beforeAll(async () => { + before(async () => { Mina.setActiveInstance(defaultNetwork); bobKey = PrivateKey.random(); @@ -88,7 +90,7 @@ describe('Test default network', () => { } }); await txn.prove(); - // failure with default enforceTransactionLimits + // failure with default bypassTransactionLimits value await expect(txn.sign([bobKey]).safeSend()).rejects.toThrow(); }); }); @@ -97,7 +99,7 @@ describe('Test enforced network', () => { let bobAccount: PublicKey, bobKey: PrivateKey; - beforeAll(async () => { + before(async () => { Mina.setActiveInstance(enforcedNetwork); bobKey = PrivateKey.random(); @@ -141,7 +143,7 @@ describe('Test enforced network', () => { } }); await txn.prove(); - // failure with enforceTransactionLimits = true + // failure with bypassTransactionLimits = false await expect(txn.sign([bobKey]).safeSend()).rejects.toThrow(); }); }); @@ -150,7 +152,7 @@ describe('Test unlimited network', () => { let bobAccount: PublicKey, bobKey: PrivateKey; - beforeAll(async () => { + before(async () => { Mina.setActiveInstance(unlimitedNetwork); bobKey = PrivateKey.random(); @@ -194,7 +196,7 @@ describe('Test unlimited network', () => { } }); await txn.prove(); - // success with enforceTransactionLimits = false + // success with bypassTransactionLimits = true await txn.sign([bobKey]).safeSend(); }); }); \ No newline at end of file diff --git a/src/lib/mina/mina.ts b/src/lib/mina/mina.ts index aba1599b2c..67edd659e5 100644 --- a/src/lib/mina/mina.ts +++ b/src/lib/mina/mina.ts @@ -104,7 +104,7 @@ function Network(options: { mina: string | string[]; archive?: string | string[]; lightnetAccountManager?: string; - enforceTransactionLimits?: boolean; + bypassTransactionLimits?: boolean; }): Mina; function Network( options: @@ -113,7 +113,7 @@ function Network( mina: string | string[]; archive?: string | string[]; lightnetAccountManager?: string; - enforceTransactionLimits?: boolean; + bypassTransactionLimits?: boolean; } | string ): Mina { @@ -162,9 +162,9 @@ function Network( Fetch.setLightnetAccountManagerEndpoint(lightnetAccountManagerEndpoint); } - if (options.enforceTransactionLimits !== undefined && - typeof options.enforceTransactionLimits === 'boolean') { - enforceTransactionLimits = options.enforceTransactionLimits; + if (options.bypassTransactionLimits !== undefined && + typeof options.bypassTransactionLimits === 'boolean') { + enforceTransactionLimits = !options.bypassTransactionLimits; } } else { throw new Error( From 8205fad5a06e4f8d84257ee7fcab1c9de96a7658 Mon Sep 17 00:00:00 2001 From: Serhii Shymkiv Date: Tue, 26 Nov 2024 15:56:25 +0200 Subject: [PATCH 191/328] Attempting to setup Nix via PATH. --- .github/workflows/build-bindings.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build-bindings.yml b/.github/workflows/build-bindings.yml index b90a01a28e..6590514bc7 100644 --- a/.github/workflows/build-bindings.yml +++ b/.github/workflows/build-bindings.yml @@ -12,6 +12,8 @@ jobs: name: build-bindings-ubuntu runs-on: [sdk-self-hosted-linux-amd64-build-system] steps: + - name: Set up Nix in PATH + run: echo "PATH=$PATH:/nix/var/nix/profiles/default/bin" >> $GITHUB_ENV - name: Disable smudging run: echo "GIT_LFS_SKIP_SMUDGE=1" >> $GITHUB_ENV - uses: actions/checkout@v4 From ed7bf0c3704e49c3fe823655367f3260ef0cb67a Mon Sep 17 00:00:00 2001 From: Serhii Shymkiv Date: Tue, 26 Nov 2024 16:14:42 +0200 Subject: [PATCH 192/328] Cleaning up. --- .github/workflows/build-bindings.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/build-bindings.yml b/.github/workflows/build-bindings.yml index 6590514bc7..3362768b11 100644 --- a/.github/workflows/build-bindings.yml +++ b/.github/workflows/build-bindings.yml @@ -12,7 +12,7 @@ jobs: name: build-bindings-ubuntu runs-on: [sdk-self-hosted-linux-amd64-build-system] steps: - - name: Set up Nix in PATH + - name: Set up Nix run: echo "PATH=$PATH:/nix/var/nix/profiles/default/bin" >> $GITHUB_ENV - name: Disable smudging run: echo "GIT_LFS_SKIP_SMUDGE=1" >> $GITHUB_ENV @@ -22,8 +22,6 @@ jobs: - name: Build the o1js bindings run: | set -Eeu - # Until we restart the runner and the PATH gets updated from /etc/bash.bashrc - export PATH="$PATH":/nix/var/nix/profiles/default/bin ./pin.sh nix develop o1js --command bash -c "npm run build:update-bindings" - name: Cleanup the Nix store From 4e4f8d8a1408faa17842de14bc22f8e997643741 Mon Sep 17 00:00:00 2001 From: querolita Date: Tue, 26 Nov 2024 16:39:35 +0100 Subject: [PATCH 193/328] remove pad and zip from external changelog --- CHANGELOG.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fffa8f30db..da97589a32 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,10 +21,6 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Compiling stuck in the browser for recursive zkprograms https://github.com/o1-labs/o1js/pull/1906 -### Added - -- Provide `zip` and `pad` for the array utility https://github.com/o1-labs/o1js/pull/1921 - ## [2.1.0](https://github.com/o1-labs/o1js/compare/b04520d...e1bac02) - 2024-11-13 ### Added From 8b94cbe650f36aed05ea355b9cd6c4e288a73c1b Mon Sep 17 00:00:00 2001 From: Serhii Shymkiv Date: Tue, 26 Nov 2024 19:09:14 +0200 Subject: [PATCH 194/328] Use unique concurrency groups for individual workflow. --- .github/workflows/benchmarks.yml | 2 +- .github/workflows/build-action.yml | 2 +- .github/workflows/build-bindings.yml | 15 ++++++++++----- .github/workflows/doc.yml | 4 ++++ .github/workflows/live-tests.yml | 2 +- 5 files changed, 17 insertions(+), 8 deletions(-) diff --git a/.github/workflows/benchmarks.yml b/.github/workflows/benchmarks.yml index f3673a3154..eb45a454cb 100644 --- a/.github/workflows/benchmarks.yml +++ b/.github/workflows/benchmarks.yml @@ -8,7 +8,7 @@ on: workflow_dispatch: {} concurrency: - group: ${{ github.ref }} + group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: diff --git a/.github/workflows/build-action.yml b/.github/workflows/build-action.yml index 402107ea05..1e3e7a3895 100644 --- a/.github/workflows/build-action.yml +++ b/.github/workflows/build-action.yml @@ -10,7 +10,7 @@ on: workflow_dispatch: {} concurrency: - group: ${{ github.ref }} + group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: diff --git a/.github/workflows/build-bindings.yml b/.github/workflows/build-bindings.yml index 7ffc1a7cff..5323c6fb39 100644 --- a/.github/workflows/build-bindings.yml +++ b/.github/workflows/build-bindings.yml @@ -1,4 +1,4 @@ -# Purpose: We want to build the o1js bindings in CI so that people in the +# Purpose: We want to build the o1js bindings in CI so that people in the # community can change them without being scared of breaking things, or # needing to do the complicated (without nix) build setup. @@ -7,19 +7,24 @@ name: Build o1js bindings on: pull_request: -jobs: +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: nix-build: name: build-bindings-ubuntu runs-on: [sdk-self-hosted-linux-amd64-build-system] steps: + - name: Set up Nix + run: echo "PATH=$PATH:/nix/var/nix/profiles/default/bin" >> $GITHUB_ENV - name: Disable smudging run: echo "GIT_LFS_SKIP_SMUDGE=1" >> $GITHUB_ENV - uses: actions/checkout@v4 with: submodules: recursive - - run: | + - name: Build the o1js bindings + run: | set -Eeu - # Until we restart the runner and the PATH gets updated from /etc/bash.bashrc - export PATH="$PATH":/nix/var/nix/profiles/default/bin ./pin.sh nix develop o1js --command bash -c "npm run build:update-bindings" diff --git a/.github/workflows/doc.yml b/.github/workflows/doc.yml index 6bd4433615..b4f7eb790a 100644 --- a/.github/workflows/doc.yml +++ b/.github/workflows/doc.yml @@ -4,6 +4,10 @@ on: branches: - main +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: Build-Doc: runs-on: ubuntu-latest diff --git a/.github/workflows/live-tests.yml b/.github/workflows/live-tests.yml index 3f14642714..dc7db700a1 100644 --- a/.github/workflows/live-tests.yml +++ b/.github/workflows/live-tests.yml @@ -13,7 +13,7 @@ on: workflow_dispatch: {} concurrency: - group: ${{ github.ref }} + group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: From ad6caee35983b0c7fd8829ea1b3804a8dffa695f Mon Sep 17 00:00:00 2001 From: Geometer1729 <16kuhnb@gmail.com> Date: Tue, 26 Nov 2024 16:46:03 -0500 Subject: [PATCH 195/328] fix in bindings --- src/bindings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bindings b/src/bindings index a5a5dc4ca2..3ac47e2d9f 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit a5a5dc4ca204285b8f088067c130f1d440f2a5b7 +Subproject commit 3ac47e2d9f3a12e8e5c0a6bb951fca9c83ea8733 From e144090f85f8da5dd3f64c57b09fe1a7d7743671 Mon Sep 17 00:00:00 2001 From: Geometer1729 <16kuhnb@gmail.com> Date: Tue, 26 Nov 2024 16:48:52 -0500 Subject: [PATCH 196/328] change pin.sh to hopefully fix issue in ci --- pin.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pin.sh b/pin.sh index c109f6733f..410f7ec9ac 100755 --- a/pin.sh +++ b/pin.sh @@ -9,6 +9,7 @@ git submodule sync && git submodule update --init --recursive # Add the flake registry entry nix registry add o1js "git+file://$ROOT?submodules=1" # update mina input to local submodule +# --override-input seems redundant but fixes a cacheing issue with local paths nix flake update mina --override-input mina 'path:src/mina' --flake '.?submodules=1' -nix flake update mina-rev --flake '.?submodules=1' +nix flake update mina-rev --flake --override-input mina-rev 'git+file:src/mina' '.?submodules=1' popd From e2e64a5291bc6180e3ca406a258dd66dedd95896 Mon Sep 17 00:00:00 2001 From: Geometer1729 <16kuhnb@gmail.com> Date: Tue, 26 Nov 2024 16:53:17 -0500 Subject: [PATCH 197/328] fix bindings commit --- src/bindings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bindings b/src/bindings index 3ac47e2d9f..9d34725117 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit 3ac47e2d9f3a12e8e5c0a6bb951fca9c83ea8733 +Subproject commit 9d347251170b7521c393e8220b246ec063a10630 From 291534cb29f5398502844f1e81d21a1727fbb6ef Mon Sep 17 00:00:00 2001 From: Geometer1729 <16kuhnb@gmail.com> Date: Tue, 26 Nov 2024 17:09:22 -0500 Subject: [PATCH 198/328] fix typo --- pin.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pin.sh b/pin.sh index 410f7ec9ac..4641ccc40f 100755 --- a/pin.sh +++ b/pin.sh @@ -11,5 +11,5 @@ nix registry add o1js "git+file://$ROOT?submodules=1" # update mina input to local submodule # --override-input seems redundant but fixes a cacheing issue with local paths nix flake update mina --override-input mina 'path:src/mina' --flake '.?submodules=1' -nix flake update mina-rev --flake --override-input mina-rev 'git+file:src/mina' '.?submodules=1' +nix flake update mina-rev --override-input mina-rev 'git+file:src/mina' --flake '.?submodules=1' popd From 9b0d399206b8d3e543298ac0703e2d4ac5abbe2d Mon Sep 17 00:00:00 2001 From: Geometer1729 <16kuhnb@gmail.com> Date: Tue, 26 Nov 2024 17:24:06 -0500 Subject: [PATCH 199/328] only use mina commit in app --- flake.lock | 484 +-------------------------------------------------- flake.nix | 11 +- pin.sh | 1 - src/bindings | 2 +- 4 files changed, 8 insertions(+), 490 deletions(-) diff --git a/flake.lock b/flake.lock index 189851c787..9b7d4e5d7f 100644 --- a/flake.lock +++ b/flake.lock @@ -48,31 +48,6 @@ "type": "github" } }, - "describe-dune_3": { - "inputs": { - "flake-utils": [ - "mina-rev", - "utils" - ], - "nixpkgs": [ - "mina-rev", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1724407960, - "narHash": "sha256-pUKTVMYEtsD1AGlHFTdPourowt+tJ3htKhRu7VALFzc=", - "owner": "o1-labs", - "repo": "describe-dune", - "rev": "be828239c05671209e979f9d5c2e3094e3be7a46", - "type": "github" - }, - "original": { - "owner": "o1-labs", - "repo": "describe-dune", - "type": "github" - } - }, "dune-nix": { "inputs": { "flake-utils": [ @@ -121,31 +96,6 @@ "type": "github" } }, - "dune-nix_3": { - "inputs": { - "flake-utils": [ - "mina-rev", - "utils" - ], - "nixpkgs": [ - "mina-rev", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1724418497, - "narHash": "sha256-HjTh7o02QhGXmbxmpE5HRWei3H/pyh/NKCMCnucDaYs=", - "owner": "o1-labs", - "repo": "dune-nix", - "rev": "26dc164a4c3976888e13eabd73a210b78505820f", - "type": "github" - }, - "original": { - "owner": "o1-labs", - "repo": "dune-nix", - "type": "github" - } - }, "flake-buildkite-pipeline": { "inputs": { "nixpkgs-lib": "nixpkgs-lib" @@ -164,24 +114,6 @@ "type": "github" } }, - "flake-buildkite-pipeline_2": { - "inputs": { - "nixpkgs-lib": "nixpkgs-lib_2" - }, - "locked": { - "lastModified": 1665561509, - "narHash": "sha256-+9KQw0ftpNjezYwbUIcLAvDWekuGSBAs8I2XulcUkT4=", - "owner": "tweag", - "repo": "flake-buildkite-pipeline", - "rev": "c836a5a449973dd04a80f6741863ceb43ec414c9", - "type": "github" - }, - "original": { - "owner": "tweag", - "repo": "flake-buildkite-pipeline", - "type": "github" - } - }, "flake-compat": { "flake": false, "locked": { @@ -214,38 +146,6 @@ "type": "github" } }, - "flake-compat_3": { - "flake": false, - "locked": { - "lastModified": 1668681692, - "narHash": "sha256-Ht91NGdewz8IQLtWZ9LCeNXMSXHUss+9COoqu6JLmXU=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "009399224d5e398d03b22badca40a37ac85412a1", - "type": "github" - }, - "original": { - "owner": "edolstra", - "repo": "flake-compat", - "type": "github" - } - }, - "flake-compat_4": { - "flake": false, - "locked": { - "lastModified": 1627913399, - "narHash": "sha256-hY8g6H2KFL8ownSiFeMOjwPC8P0ueXpCVEbxgda3pko=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "12c64ca55c1014cdc1b16ed5a804aa8576601ff2", - "type": "github" - }, - "original": { - "owner": "edolstra", - "repo": "flake-compat", - "type": "github" - } - }, "flake-utils": { "inputs": { "systems": "systems" @@ -309,51 +209,6 @@ "type": "github" } }, - "flake-utils_5": { - "locked": { - "lastModified": 1623875721, - "narHash": "sha256-A8BU7bjS5GirpAUv4QA+QnJ4CceLHkcXdRp4xITDB0s=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "f7e004a55b120c02ecb6219596820fcd32ca8772", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "flake-utils_6": { - "locked": { - "lastModified": 1638122382, - "narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "74f7e4319258e287b0f9cb95426c9853b282730b", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "flake-utils_7": { - "locked": { - "lastModified": 1644229661, - "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, "flockenzeit": { "locked": { "lastModified": 1671184471, @@ -369,21 +224,6 @@ "type": "github" } }, - "flockenzeit_2": { - "locked": { - "lastModified": 1671184471, - "narHash": "sha256-oTsIo40BxHG8ZcMNwJybV68F8CLNdfY9HKFzEBzeJ6A=", - "owner": "balsoft", - "repo": "Flockenzeit", - "rev": "0409dcd0cc87feebd211c529171d61b89f10d9b3", - "type": "github" - }, - "original": { - "owner": "balsoft", - "repo": "Flockenzeit", - "type": "github" - } - }, "gitignore-nix": { "inputs": { "nixpkgs": [ @@ -405,27 +245,6 @@ "type": "github" } }, - "gitignore-nix_2": { - "inputs": { - "nixpkgs": [ - "mina-rev", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1660459072, - "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=", - "owner": "hercules-ci", - "repo": "gitignore.nix", - "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "gitignore.nix", - "type": "github" - } - }, "mina": { "inputs": { "describe-dune": "describe-dune_2", @@ -456,38 +275,6 @@ "type": "path" } }, - "mina-rev": { - "inputs": { - "describe-dune": "describe-dune_3", - "dune-nix": "dune-nix_3", - "flake-buildkite-pipeline": "flake-buildkite-pipeline_2", - "flake-compat": "flake-compat_3", - "flockenzeit": "flockenzeit_2", - "gitignore-nix": "gitignore-nix_2", - "mix-to-nix": "mix-to-nix_2", - "nix-filter": "nix-filter_2", - "nix-npm-buildPackage": "nix-npm-buildPackage_2", - "nix-utils": "nix-utils_2", - "nixpkgs": "nixpkgs_4", - "nixpkgs-mozilla": "nixpkgs-mozilla_2", - "o1-opam-repository": "o1-opam-repository_2", - "opam-nix": "opam-nix_2", - "opam-repository": "opam-repository_2", - "utils": "utils_2" - }, - "locked": { - "lastModified": 1729507624, - "narHash": "sha256-DudL1W06R1K0HYyetAVZSzao5B5fjS/rS6cMfCBhiqE=", - "rev": "6899054b745c1323b9d5bcaa62c00bed2ad1ead3", - "revCount": 32900, - "type": "git", - "url": "file:src/mina" - }, - "original": { - "type": "git", - "url": "file:src/mina" - } - }, "mirage-opam-overlays": { "flake": false, "locked": { @@ -504,22 +291,6 @@ "type": "github" } }, - "mirage-opam-overlays_2": { - "flake": false, - "locked": { - "lastModified": 1661959605, - "narHash": "sha256-CPTuhYML3F4J58flfp3ZbMNhkRkVFKmBEYBZY5tnQwA=", - "owner": "dune-universe", - "repo": "mirage-opam-overlays", - "rev": "05f1c1823d891ce4d8adab91f5db3ac51d86dc0b", - "type": "github" - }, - "original": { - "owner": "dune-universe", - "repo": "mirage-opam-overlays", - "type": "github" - } - }, "mix-to-nix": { "locked": { "lastModified": 1643291492, @@ -535,21 +306,6 @@ "type": "github" } }, - "mix-to-nix_2": { - "locked": { - "lastModified": 1643291492, - "narHash": "sha256-B+VIFF8qDJhF5hVMc8PbY/WPzUtbGgjsV1eAxTt5GuQ=", - "owner": "serokell", - "repo": "mix-to-nix", - "rev": "f6f0172b3ac4d32c0e6050a7d805734de0b7adef", - "type": "github" - }, - "original": { - "owner": "serokell", - "repo": "mix-to-nix", - "type": "github" - } - }, "nix-filter": { "locked": { "lastModified": 1666547822, @@ -565,21 +321,6 @@ "type": "github" } }, - "nix-filter_2": { - "locked": { - "lastModified": 1666547822, - "narHash": "sha256-razwnAybPHyoAyhkKCwXdxihIqJi1G6e1XP4FQOJTEs=", - "owner": "numtide", - "repo": "nix-filter", - "rev": "1a3b735e13e90a8d2fd5629f2f8363bd7ffbbec7", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "nix-filter", - "type": "github" - } - }, "nix-npm-buildPackage": { "inputs": { "nixpkgs": [ @@ -601,27 +342,6 @@ "type": "github" } }, - "nix-npm-buildPackage_2": { - "inputs": { - "nixpkgs": [ - "mina-rev", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1670813451, - "narHash": "sha256-v0IvQ35CMKtPreGlxWb1FvFUraJNZd144+MbiDwGoAA=", - "owner": "serokell", - "repo": "nix-npm-buildpackage", - "rev": "ec0365cd14a3359a23b80a9e2531a09afc3488fc", - "type": "github" - }, - "original": { - "owner": "serokell", - "repo": "nix-npm-buildpackage", - "type": "github" - } - }, "nix-utils": { "inputs": { "flake-utils": "flake-utils_2", @@ -641,25 +361,6 @@ "type": "github" } }, - "nix-utils_2": { - "inputs": { - "flake-utils": "flake-utils_5", - "nixpkgs": "nixpkgs_3" - }, - "locked": { - "lastModified": 1632973430, - "narHash": "sha256-9G8zo+0nfYAALV5umCyQR/2hVUFNH10JropBkyxZGGw=", - "owner": "juliosueiras-nix", - "repo": "nix-utils", - "rev": "b44e1ffd726aa03056db9df469efb497d8b9871b", - "type": "github" - }, - "original": { - "owner": "juliosueiras-nix", - "repo": "nix-utils", - "type": "github" - } - }, "nixpkgs": { "locked": { "lastModified": 1629252929, @@ -690,21 +391,6 @@ "type": "github" } }, - "nixpkgs-lib_2": { - "locked": { - "lastModified": 1649551420, - "narHash": "sha256-J/Pn38rBZTszdtTHhhxroQaHADhd5TgbJ53F9j1WTIE=", - "owner": "nix-community", - "repo": "nixpkgs.lib", - "rev": "3a16841c57b0d3025b21b869cc921a119ce73033", - "type": "github" - }, - "original": { - "owner": "nix-community", - "repo": "nixpkgs.lib", - "type": "github" - } - }, "nixpkgs-mozilla": { "flake": false, "locked": { @@ -737,22 +423,6 @@ "type": "github" } }, - "nixpkgs-mozilla_3": { - "flake": false, - "locked": { - "lastModified": 1704373101, - "narHash": "sha256-+gi59LRWRQmwROrmE1E2b3mtocwueCQqZ60CwLG+gbg=", - "owner": "mozilla", - "repo": "nixpkgs-mozilla", - "rev": "9b11a87c0cc54e308fa83aac5b4ee1816d5418a2", - "type": "github" - }, - "original": { - "owner": "mozilla", - "repo": "nixpkgs-mozilla", - "type": "github" - } - }, "nixpkgs_2": { "locked": { "lastModified": 1713180868, @@ -770,37 +440,6 @@ } }, "nixpkgs_3": { - "locked": { - "lastModified": 1629252929, - "narHash": "sha256-Aj20gmGBs8TG7pyaQqgbsqAQ6cB+TVuL18Pk3DPBxcQ=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "3788c68def67ca7949e0864c27638d484389363d", - "type": "github" - }, - "original": { - "owner": "nixos", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_4": { - "locked": { - "lastModified": 1713180868, - "narHash": "sha256-5CSnPSCEWeUmrFiLuYIQIPQzPrpCB8x3VhE+oXLRO3k=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "140546acf30a8212a03a88ded8506413fa3b5d21", - "type": "github" - }, - "original": { - "owner": "nixos", - "ref": "nixos-23.11-small", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_5": { "locked": { "lastModified": 1720535198, "narHash": "sha256-zwVvxrdIzralnSbcpghA92tWu2DV2lwv89xZc8MTrbg=", @@ -832,22 +471,6 @@ "type": "github" } }, - "o1-opam-repository_2": { - "flake": false, - "locked": { - "lastModified": 1715294616, - "narHash": "sha256-W2p9Vs8PqpKGvMByxVqpxAljjpEMqNcuNnjMBAAKicI=", - "owner": "o1-labs", - "repo": "opam-repository", - "rev": "38d6995e307c82b3c0b3bc86a867213db724d1c5", - "type": "github" - }, - "original": { - "owner": "o1-labs", - "repo": "opam-repository", - "type": "github" - } - }, "opam-nix": { "inputs": { "flake-compat": "flake-compat_2", @@ -878,36 +501,6 @@ "type": "github" } }, - "opam-nix_2": { - "inputs": { - "flake-compat": "flake-compat_4", - "flake-utils": "flake-utils_6", - "mirage-opam-overlays": "mirage-opam-overlays_2", - "nixpkgs": [ - "mina-rev", - "nixpkgs" - ], - "opam-overlays": "opam-overlays_2", - "opam-repository": [ - "mina-rev", - "opam-repository" - ], - "opam2json": "opam2json_2" - }, - "locked": { - "lastModified": 1712645768, - "narHash": "sha256-9dUh8nElGtC74Q4gIDV6DM0FKgF1oXh0PUkCxdbp+sg=", - "owner": "tweag", - "repo": "opam-nix", - "rev": "464863fba44c7ecc50bd1a2967274482a2c33daf", - "type": "github" - }, - "original": { - "owner": "tweag", - "repo": "opam-nix", - "type": "github" - } - }, "opam-overlays": { "flake": false, "locked": { @@ -924,22 +517,6 @@ "type": "github" } }, - "opam-overlays_2": { - "flake": false, - "locked": { - "lastModified": 1654162756, - "narHash": "sha256-RV68fUK+O3zTx61iiHIoS0LvIk0E4voMp+0SwRg6G6c=", - "owner": "dune-universe", - "repo": "opam-overlays", - "rev": "c8f6ef0fc5272f254df4a971a47de7848cc1c8a4", - "type": "github" - }, - "original": { - "owner": "dune-universe", - "repo": "opam-overlays", - "type": "github" - } - }, "opam-repository": { "flake": false, "locked": { @@ -956,22 +533,6 @@ "type": "github" } }, - "opam-repository_2": { - "flake": false, - "locked": { - "lastModified": 1708601497, - "narHash": "sha256-mDYINTjOiYLN4wT5fGlWTvHFQdWkzY46XUuZWKgmJxY=", - "owner": "ocaml", - "repo": "opam-repository", - "rev": "90d8c520a4f0b035ac51e267a8b33739c5a78b5a", - "type": "github" - }, - "original": { - "owner": "ocaml", - "repo": "opam-repository", - "type": "github" - } - }, "opam2json": { "inputs": { "nixpkgs": [ @@ -994,37 +555,14 @@ "type": "github" } }, - "opam2json_2": { - "inputs": { - "nixpkgs": [ - "mina-rev", - "opam-nix", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1671540003, - "narHash": "sha256-5pXfbUfpVABtKbii6aaI2EdAZTjHJ2QntEf0QD2O5AM=", - "owner": "tweag", - "repo": "opam2json", - "rev": "819d291ea95e271b0e6027679de6abb4d4f7f680", - "type": "github" - }, - "original": { - "owner": "tweag", - "repo": "opam2json", - "type": "github" - } - }, "root": { "inputs": { "describe-dune": "describe-dune", "dune-nix": "dune-nix", "flake-utils": "flake-utils", "mina": "mina", - "mina-rev": "mina-rev", - "nixpkgs": "nixpkgs_5", - "nixpkgs-mozilla": "nixpkgs-mozilla_3" + "nixpkgs": "nixpkgs_3", + "nixpkgs-mozilla": "nixpkgs-mozilla_2" } }, "systems": { @@ -1059,24 +597,6 @@ "repo": "flake-utils-plus", "type": "github" } - }, - "utils_2": { - "inputs": { - "flake-utils": "flake-utils_7" - }, - "locked": { - "lastModified": 1657226504, - "narHash": "sha256-GIYNjuq4mJlFgqKsZ+YrgzWm0IpA4axA3MCrdKYj7gs=", - "owner": "gytis-ivaskevicius", - "repo": "flake-utils-plus", - "rev": "2bf0f91643c2e5ae38c1b26893ac2927ac9bd82a", - "type": "github" - }, - "original": { - "owner": "gytis-ivaskevicius", - "repo": "flake-utils-plus", - "type": "github" - } } }, "root": "root", diff --git a/flake.nix b/flake.nix index 007158f4de..40ccdfe2ea 100644 --- a/flake.nix +++ b/flake.nix @@ -3,10 +3,6 @@ inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixos-23.11-small"; mina.url = "path:src/mina"; - # Nix doesn't seem to handle recursive submodules well - # so we import mina once not as a git repo so the submodules work - # but also as a git repo so the git rev is visible - mina-rev.url = "git+file:src/mina"; nixpkgs-mozilla.url = "github:mozilla/nixpkgs-mozilla"; nixpkgs-mozilla.flake = false; describe-dune.url = "github:o1-labs/describe-dune"; @@ -227,7 +223,7 @@ "${mina.files.src-lib-crypto-kimchi_bindings-js-node_js}/src/lib/crypto/kimchi_bindings/js/node_js"; EXPORT_TEST_VECTORS = "${test-vectors}/bin/export_test_vectors"; buildInputs = bindings-pkgs ++ [ pkgs.bash ]; - MINA_COMMIT = inputs.mina-rev.rev; + SKIP_MINA_COMMIT = true; patchPhase = '' patchShebangs ./src/bindings/scripts/ patchShebangs ./src/bindings/crypto/test-vectors/ @@ -243,7 +239,7 @@ mkdir $out pushd ./src/bindings rm -rf ./compiled/_node_bindings - cp -Lr ./compiled ./mina-transaction ./ocaml ./MINA_COMMIT $out + cp -Lr ./compiled ./mina-transaction ./ocaml $out popd ''; }; @@ -258,6 +254,9 @@ text = '' cp -r ${self.packages."${system}".o1js-bindings}/* ./src/bindings + MINA_COMMIT=$(git -C src/mina rev-parse HEAD) + echo "The mina commit used to generate the backends for node and web is" "$MINA_COMMIT" \ + > src/bindings/MINA_COMMIT ''; }}/bin/update-bindings"; }; diff --git a/pin.sh b/pin.sh index 4641ccc40f..e56e8e4425 100755 --- a/pin.sh +++ b/pin.sh @@ -11,5 +11,4 @@ nix registry add o1js "git+file://$ROOT?submodules=1" # update mina input to local submodule # --override-input seems redundant but fixes a cacheing issue with local paths nix flake update mina --override-input mina 'path:src/mina' --flake '.?submodules=1' -nix flake update mina-rev --override-input mina-rev 'git+file:src/mina' --flake '.?submodules=1' popd diff --git a/src/bindings b/src/bindings index 9d34725117..69299e08de 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit 9d347251170b7521c393e8220b246ec063a10630 +Subproject commit 69299e08deefe3bd2381bfe5d9eafa183e904a15 From ba7ad0ef7ec8ed089289819ea634ab80263585fa Mon Sep 17 00:00:00 2001 From: Florian Date: Wed, 27 Nov 2024 12:01:06 +0700 Subject: [PATCH 200/328] revert bindings, hopefully --- src/bindings | 2 +- src/mina | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bindings b/src/bindings index 015333ff22..66781be42f 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit 015333ff220ed723f12580acfd6a6beab593072f +Subproject commit 66781be42fbb79cdd95eee5466935940fa4a6d30 diff --git a/src/mina b/src/mina index 9bdaae9990..6899054b74 160000 --- a/src/mina +++ b/src/mina @@ -1 +1 @@ -Subproject commit 9bdaae99904c13e3e10841ec6b778e45cdacabfb +Subproject commit 6899054b745c1323b9d5bcaa62c00bed2ad1ead3 From 4a0bbd803a7aaed094d15755f29de173416defc1 Mon Sep 17 00:00:00 2001 From: Florian Date: Wed, 27 Nov 2024 12:02:05 +0700 Subject: [PATCH 201/328] revert bindings commit --- src/bindings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bindings b/src/bindings index 66781be42f..2c62a9a755 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit 66781be42fbb79cdd95eee5466935940fa4a6d30 +Subproject commit 2c62a9a755f1b128f89cc2131814df7157f68109 From 7ffd643871f925bbcb23da5456971f6a3c26f567 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Wed, 27 Nov 2024 16:18:58 +0800 Subject: [PATCH 202/328] refactor(program-with-non-pure-input.ts): remove unused import Provable from o1js to clean up code and improve readability --- src/examples/zkprogram/program-with-non-pure-input.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/examples/zkprogram/program-with-non-pure-input.ts b/src/examples/zkprogram/program-with-non-pure-input.ts index ca4355b408..f217ed8721 100644 --- a/src/examples/zkprogram/program-with-non-pure-input.ts +++ b/src/examples/zkprogram/program-with-non-pure-input.ts @@ -1,4 +1,4 @@ -import { Field, Provable, Struct, ZkProgram, assert } from 'o1js'; +import { Field, Struct, ZkProgram, assert } from 'o1js'; class MyStruct extends Struct({ label: String, From 610b2eb56da96c2ce72b22dca4d30c9652500b80 Mon Sep 17 00:00:00 2001 From: querolita Date: Wed, 27 Nov 2024 12:10:10 +0100 Subject: [PATCH 203/328] optional error message in assert none --- src/lib/provable/option.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib/provable/option.ts b/src/lib/provable/option.ts index c579e2401f..edec98d60e 100644 --- a/src/lib/provable/option.ts +++ b/src/lib/provable/option.ts @@ -9,7 +9,7 @@ export { Option, OptionOrValue }; type Option = { isSome: Bool; value: T } & { assertSome(message?: string): T; - assertNone(): void; + assertNone(message?: string): void; orElse(defaultValue: T | V): T; }; @@ -105,8 +105,8 @@ function Option( return this.value; } - assertNone(): void { - this.isSome.assertFalse(); + assertNone(message?: string): void { + this.isSome.assertFalse(message); } static from(value?: V | T) { From d957245ba98868dbb371bdf9005e47cec249ac05 Mon Sep 17 00:00:00 2001 From: querolita Date: Wed, 27 Nov 2024 13:44:38 +0100 Subject: [PATCH 204/328] change behavior of zip to allow nonequal array lengths --- src/lib/util/arrays.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/lib/util/arrays.ts b/src/lib/util/arrays.ts index d282ba607e..99a33fc0ac 100644 --- a/src/lib/util/arrays.ts +++ b/src/lib/util/arrays.ts @@ -17,7 +17,10 @@ function chunkString(str: string, size: number): string[] { } function zip(a: T[], b: S[]) { - assert(a.length === b.length, 'zip(): arrays of unequal length'); + assert( + a.length <= b.length, + 'zip(): first array must be at least as long as the second array' + ); return a.map((a, i): [T, S] => [a, b[i]!]); } From 02c6d5680be008c06a60544a055da629a8c22d28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ana=C3=AFs=20Querol?= Date: Wed, 27 Nov 2024 13:46:43 +0100 Subject: [PATCH 205/328] use back quotes to correctly format chunk error message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Boray Saygılıer --- src/lib/util/arrays.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/util/arrays.ts b/src/lib/util/arrays.ts index 99a33fc0ac..f3a59b5388 100644 --- a/src/lib/util/arrays.ts +++ b/src/lib/util/arrays.ts @@ -5,7 +5,7 @@ export { chunk, chunkString, zip, pad }; function chunk(array: T[], size: number): T[][] { assert( array.length % size === 0, - 'chunk(): invalid input length, it must be a multiple of ${size}' + `chunk(): invalid input length, it must be a multiple of ${size}` ); return Array.from({ length: array.length / size }, (_, i) => array.slice(size * i, size * (i + 1)) From 1eac01ed8e96f79854113f1ad8d5379eb064f5d3 Mon Sep 17 00:00:00 2001 From: querolita Date: Wed, 27 Nov 2024 14:47:44 +0100 Subject: [PATCH 206/328] fix assertion message --- src/lib/util/arrays.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/util/arrays.ts b/src/lib/util/arrays.ts index 99a33fc0ac..320db44001 100644 --- a/src/lib/util/arrays.ts +++ b/src/lib/util/arrays.ts @@ -19,7 +19,7 @@ function chunkString(str: string, size: number): string[] { function zip(a: T[], b: S[]) { assert( a.length <= b.length, - 'zip(): first array must be at least as long as the second array' + 'zip(): second array must be at least as long as the first array' ); return a.map((a, i): [T, S] => [a, b[i]!]); } From d36fdc899b12470a943129bb361f481f1dff9cf0 Mon Sep 17 00:00:00 2001 From: Gregor Date: Wed, 27 Nov 2024 16:53:03 +0100 Subject: [PATCH 207/328] expose proof <-> base64 conversion --- src/lib/proof-system/proof.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/lib/proof-system/proof.ts b/src/lib/proof-system/proof.ts index 9111482cf9..95f60a2e0f 100644 --- a/src/lib/proof-system/proof.ts +++ b/src/lib/proof-system/proof.ts @@ -92,6 +92,13 @@ class ProofBase { publicFields() { return (this.constructor as typeof ProofBase).publicFields(this); } + + static _proofFromBase64(proofString: string, maxProofsVerified: 0 | 1 | 2) { + return Pickles.proofOfBase64(proofString, maxProofsVerified)[1]; + } + static _proofToBase64(proof: Pickles.Proof, maxProofsVerified: 0 | 1 | 2) { + return Pickles.proofToBase64([maxProofsVerified, proof]); + } } class Proof extends ProofBase { From 7cd1bf77dc628615d16999632c27d47f804b5c01 Mon Sep 17 00:00:00 2001 From: Gregor Date: Wed, 27 Nov 2024 17:15:00 +0100 Subject: [PATCH 208/328] changelog --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 48876c95f6..86e0a8b5af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,10 +17,13 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ## [Unreleased](https://github.com/o1-labs/o1js/compare/e1bac02...HEAD) +### Added + +- Expose low-level conversion methods `Proof.{_proofToBase64,_proofFromBase64}` https://github.com/o1-labs/o1js/pull/1928 + ### Fixed - Compiling stuck in the browser for recursive zkprograms https://github.com/o1-labs/o1js/pull/1906 - - Error message in `rangeCheck16` gadget https://github.com/o1-labs/o1js/pull/1920 ## [2.1.0](https://github.com/o1-labs/o1js/compare/b04520d...e1bac02) - 2024-11-13 From aa9548065464540c3b1ce0880dcfe40f9c048c69 Mon Sep 17 00:00:00 2001 From: querolita Date: Wed, 27 Nov 2024 17:26:41 +0100 Subject: [PATCH 209/328] update steps --- README-nix.md | 77 +++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 68 insertions(+), 9 deletions(-) diff --git a/README-nix.md b/README-nix.md index 9f9d7fcc91..2defa96754 100644 --- a/README-nix.md +++ b/README-nix.md @@ -22,8 +22,8 @@ sh <(curl -L https://nixos.org/nix/install) --daemon ``` If you're unsure about your Nix setup, the assistant will guide you towards a -clean installation. It will involve backing up your old `/etc/X` and `/etc/X.backup-before-nix` for `X = {bashrc, zshrc}`, and finally uninstalling and -reinstalling Nix from scratch. +clean installation. It will involve backing up your old `/etc/X` and `/etc/X.backup-before-nix` for `X = {bash.bashrc, bashrc, zshrc}`, and finally +uninstalling and reinstalling Nix from scratch. > **warning for macOS users**: macOS updates will often break your nix > installation. To prevent that, you can add the following to your `~/.bashrc` @@ -54,25 +54,37 @@ expressions in this repository, or want to get some convenience features and speed improvements, **it is advisable to enable flakes**. For this, you'll want to make sure you're running recent Nix (⩾2.5) and have enabled the relevant experimental features, either in -`/etc/nix/nix.conf` or (recommended) in `~/.config/nix/nix.conf`: +`/etc/nix/nix.conf` or (recommended) in `~/.config/nix/nix.conf` (meaning to add +`experimental-features = nix-command flakes` in that file): -``` +```console mkdir -p "${XDG_CONFIG_HOME-${HOME}/.config}/nix" echo 'experimental-features = nix-command flakes' > "${XDG_CONFIG_HOME-${HOME}/.config}/nix/nix.conf" ``` -You can check that your flake support is working by running `nix flake metadata -github:nixos/nixpkgs` for example. +Verify your flake support is working by running: + +```console +nix flake metadata github:nixos/nixpkgs +``` ## Building with Nix +Start by cloning the repository. Optionally, you can install dependencies with +`npm i`, but Nix should take care of all the packages. + +```bash +git clone --recurse-submodules git@github.com:o1-labs/o1js.git +cd o1js +# npm install +``` + From a new shell, go to `{REPO_PATH}/o1js` and from there execute `./pin.sh` to update the submodules and add the flakes entries. Then, you can open a Nix shell with all the dependencies required executing `nix develop o1js#default`, or alternatively `nix develop o1js#mina-shell` (which works better from MacOS). ```console -cd {REPO_PATH}/o1js ./pin.sh nix develop o1js#default ``` @@ -80,6 +92,20 @@ nix develop o1js#default You will observe that the current devshell becomes a Nix shell with the right configuration for `o1js` and `mina`. +In order to make sure that the bindings will be regenerated in the case that you +are modifying them, make sure to comment out the conditionals in +`src/mina/src/lib/crypto/kimchi_bindings/js/node_js/build.sh` and `src/mina/src/lib/crypto/kimchi_bindings/js/web/build.sh` locally. That's because otherwise the +PLONK_WASM_WEB check prevents `proof-systems` from compiling with each build. + +```sh +if true; then # [[ -z "${PLONK_WASM_WEB-}" ]]; then + export RUSTFLAGS="-C target-feature=+atomics,+bulk-memory,+mutable-globals -C link-arg=--no-check-features -C link-arg=--max-memory=4294967296" + rustup run nightly-2023-09-01 wasm-pack build --target web --out-dir ../js/web ../../wasm -- -Z build-std=panic_abort,std +else + cp "$PLONK_WASM_WEB"/* -R . +fi +``` + Then, you can build o1js and update the bindings. ```console @@ -88,7 +114,14 @@ npm run build:update-bindings ``` If you need to update the underlying `mina` code, you can also do so with Nix, -but from the corresopnding subdirectory. +but from the corresopnding subdirectory. In particular, you should build Mina +from the o1js subdirectory from a Nix shell. That means, + +```console +cd ./src/mina +./nix/pin.sh +nix develop mina +``` ## Common errors @@ -130,6 +163,13 @@ export CPPFLAGS="-I/opt/homebrew/opt/libiconv/include" export LIBRARY_PATH="/opt/homebrew/opt/libiconv/lib:$LIBRARY_PATH" ``` +Alternatively, try this change in the `src/mina/flake.nix` file: + +``` +- devShellPackages = with pkgs; [ rosetta-cli wasm-pack nodejs binaryen ]; ++ devShellPackages = with pkgs; [ rosetta-cli wasm-pack nodejs binaryen cargo libiconvI]; +``` + ### wasm32-unknown-unknown The rust compiler and/or Wasm-pack might not be correctly setup in the Nix shell. @@ -209,4 +249,23 @@ error: "/nix/store/w30zw23kmgks77d870i502a3185hjycv-rust/lib/rustlib/src/rust/Ca #### Fix -Install `cargo` on your host machine. +Install `cargo` on your host machine. If doing so does not solve the problem, it +is very likely that the whole Nix setup has gone wrong and it is very adviceable +to install it from scratch. + +### Old path + +When several clones of the repository are present in the system and both have +used Nix (or if it has been moved from one location to another), Nix might cache +an old path, impossibilitating builds. For example, typing `nix develop mina` +would complain and produce the following error: + +```console +error: resolving Git reference 'master': revspec 'master' not found +``` + +Then, the error message would still contain old directories. + +#### Fix + +Create a new environment for Nix and start from scratch. From 7a2f19a3e0c503ab003bd18faa54a7beb784e29f Mon Sep 17 00:00:00 2001 From: Gregor Date: Wed, 27 Nov 2024 17:50:39 +0100 Subject: [PATCH 210/328] create program state by default (we'll need it) --- src/lib/proof-system/zkprogram.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 26b06039eb..9104153ef1 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -796,7 +796,7 @@ function picklesRuleFromFunction( proofSystemTag: { name: string }, { methodName, args, auxiliaryType }: MethodInterface, gates: Gate[], - state?: ReturnType + state: ReturnType = createProgramState() ): Pickles.Rule { async function main( publicInput: MlFieldArray @@ -875,11 +875,7 @@ function picklesRuleFromFunction( ? publicOutputType.toFields(result.publicOutput) : []; - if ( - state !== undefined && - auxiliaryType !== undefined && - auxiliaryType.sizeInFields() !== 0 - ) { + if (auxiliaryType !== undefined && auxiliaryType.sizeInFields() !== 0) { Provable.asProver(() => { let { auxiliaryOutput } = result; assert( From fce135e4b5b27dc89f1a2e1f138fa78078bfeba3 Mon Sep 17 00:00:00 2001 From: Coby Date: Wed, 27 Nov 2024 12:42:18 -0500 Subject: [PATCH 211/328] automatically tag version number after release --- .github/workflows/build-action.yml | 14 ++++++++++++++ .github/workflows/release.yml | 13 +++++++++++++ 2 files changed, 27 insertions(+) diff --git a/.github/workflows/build-action.yml b/.github/workflows/build-action.yml index 402107ea05..732cd6d108 100644 --- a/.github/workflows/build-action.yml +++ b/.github/workflows/build-action.yml @@ -301,6 +301,8 @@ jobs: run: | npm ci npm run prepublishOnly + + - name: Publish to NPM if version has changed uses: JS-DevTools/npm-publish@v3 with: @@ -308,6 +310,18 @@ jobs: strategy: upgrade env: INPUT_TOKEN: ${{ secrets.NPM_TOKEN }} + + - name: Determine released version + id: version + run: echo "::set-output name=version::$(node -p "require('./package.json').version")" + + - name: Tag new version + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN}} + RELEASED_VERSION: ${{ steps.version.outputs.version }} + run: | + git tag $RELEASED_VERSION + git push origin $RELEASED_VERSION Release-mina-signer-on-NPM: if: github.ref == 'refs/heads/main' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 67e89f95bb..a2bdeb66d8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -80,3 +80,16 @@ jobs: gh pr create --base main --head $NEW_BRANCH --title "Release $NEW_VERSION [CHECK SEMVER BEFORE MERGE]" --body "This is an automated PR to update to version $NEW_VERSION. Please check [SemVer](https://semver.org/) for correct versioning before merging this PR." env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN}} + + - name: Determine released version + id: version + run: echo "::set-output name=version::$(node -p "require('./package.json').version")" + + - name: Tag new version + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN}} + RELEASED_VERSION: ${{ steps.version.outputs.version }} + run: | + git tag $RELEASED_VERSION + git push origin $RELEASED_VERSION + From a736d3ebcff4616e00ac59e45ee7e186d37689d8 Mon Sep 17 00:00:00 2001 From: Coby Date: Wed, 27 Nov 2024 12:48:59 -0500 Subject: [PATCH 212/328] use release step output instead --- .github/workflows/build-action.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build-action.yml b/.github/workflows/build-action.yml index 732cd6d108..3c43c04f95 100644 --- a/.github/workflows/build-action.yml +++ b/.github/workflows/build-action.yml @@ -304,6 +304,7 @@ jobs: - name: Publish to NPM if version has changed + id: publish uses: JS-DevTools/npm-publish@v3 with: token: ${{ secrets.NPM_TOKEN }} @@ -311,18 +312,16 @@ jobs: env: INPUT_TOKEN: ${{ secrets.NPM_TOKEN }} - - name: Determine released version - id: version - run: echo "::set-output name=version::$(node -p "require('./package.json').version")" - - name: Tag new version + if: ${{ steps.publish.outputs.type }} # https://github.com/JS-DevTools/npm-publish?tab=readme-ov-file#action-output env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN}} - RELEASED_VERSION: ${{ steps.version.outputs.version }} + RELEASED_VERSION: ${{ steps.publish.outputs.version }} run: | git tag $RELEASED_VERSION git push origin $RELEASED_VERSION + Release-mina-signer-on-NPM: if: github.ref == 'refs/heads/main' timeout-minutes: 180 From c785a526c3d86880837dfe8972c00473b31e1d76 Mon Sep 17 00:00:00 2001 From: Coby Date: Wed, 27 Nov 2024 12:49:52 -0500 Subject: [PATCH 213/328] nit --- .github/workflows/build-action.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/build-action.yml b/.github/workflows/build-action.yml index 3c43c04f95..8d7844e142 100644 --- a/.github/workflows/build-action.yml +++ b/.github/workflows/build-action.yml @@ -302,7 +302,6 @@ jobs: npm ci npm run prepublishOnly - - name: Publish to NPM if version has changed id: publish uses: JS-DevTools/npm-publish@v3 @@ -315,7 +314,7 @@ jobs: - name: Tag new version if: ${{ steps.publish.outputs.type }} # https://github.com/JS-DevTools/npm-publish?tab=readme-ov-file#action-output env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN}} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} RELEASED_VERSION: ${{ steps.publish.outputs.version }} run: | git tag $RELEASED_VERSION From 7dc66b540a2ae7b841f065b06983498f63fbb4ef Mon Sep 17 00:00:00 2001 From: Coby Date: Wed, 27 Nov 2024 12:50:38 -0500 Subject: [PATCH 214/328] rm release yml changes --- .github/workflows/release.yml | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a2bdeb66d8..67e89f95bb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -80,16 +80,3 @@ jobs: gh pr create --base main --head $NEW_BRANCH --title "Release $NEW_VERSION [CHECK SEMVER BEFORE MERGE]" --body "This is an automated PR to update to version $NEW_VERSION. Please check [SemVer](https://semver.org/) for correct versioning before merging this PR." env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN}} - - - name: Determine released version - id: version - run: echo "::set-output name=version::$(node -p "require('./package.json').version")" - - - name: Tag new version - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN}} - RELEASED_VERSION: ${{ steps.version.outputs.version }} - run: | - git tag $RELEASED_VERSION - git push origin $RELEASED_VERSION - From c700b18daa713555cca123fa86cc71a3f44711dc Mon Sep 17 00:00:00 2001 From: Gregor Date: Thu, 28 Nov 2024 08:22:23 +0100 Subject: [PATCH 215/328] lift collection of declared proofs into its own global context --- src/lib/proof-system/zkprogram-context.ts | 28 +++++++++++++ src/lib/proof-system/zkprogram.ts | 50 ++++++++++++++--------- 2 files changed, 58 insertions(+), 20 deletions(-) create mode 100644 src/lib/proof-system/zkprogram-context.ts diff --git a/src/lib/proof-system/zkprogram-context.ts b/src/lib/proof-system/zkprogram-context.ts new file mode 100644 index 0000000000..955e61b366 --- /dev/null +++ b/src/lib/proof-system/zkprogram-context.ts @@ -0,0 +1,28 @@ +import { Context } from '../util/global-context.js'; +import type { Subclass } from '../util/types.js'; +import type { ProofBase } from './proof.js'; + +export { ZkProgramContext, DeclaredProof }; + +type DeclaredProof = { + Proof: Subclass>; + proof: ProofBase; +}; +type ZkProgramContext = { + proofs: DeclaredProof[]; +}; +let context = Context.create(); + +const ZkProgramContext = { + enter() { + return context.enter({ proofs: [] }); + }, + leave: context.leave, + + declareProof(proof: DeclaredProof) { + context.get().proofs.push(proof); + }, + getDeclaredProofs() { + return context.get().proofs; + }, +}; diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 9104153ef1..a1159dd894 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -53,6 +53,7 @@ import { } from './feature-flags.js'; import { emptyWitness } from '../provable/types/util.js'; import { InferValue } from '../../bindings/lib/provable-generic.js'; +import { DeclaredProof, ZkProgramContext } from './zkprogram-context.js'; // public API export { @@ -803,15 +804,12 @@ function picklesRuleFromFunction( ): ReturnType { let { witnesses: argsWithoutPublicInput, inProver } = snarkContext.get(); assert(!(inProver && argsWithoutPublicInput === undefined)); + + let id = ZkProgramContext.enter(); let finalArgs = []; - let proofs: { - Proof: Subclass>; - proof: ProofBase; - }[] = []; - let previousStatements: Pickles.Statement[] = []; for (let i = 0; i < args.length; i++) { - let type = args[i]; try { + let type = args[i]; let value = Provable.witness(type, () => { return argsWithoutPublicInput?.[i] ?? ProvableType.synthesize(type); }); @@ -819,28 +817,40 @@ function picklesRuleFromFunction( for (let proof of extractProofs(value)) { let Proof = proof.constructor as Subclass>; - proofs.push({ Proof, proof }); - let fields = proof.publicFields(); - let input = MlFieldArray.to(fields.input); - let output = MlFieldArray.to(fields.output); - previousStatements.push(MlPair(input, output)); + ZkProgramContext.declareProof({ Proof, proof }); } } catch (e: any) { + ZkProgramContext.leave(id); e.message = `Error when witnessing in ${methodName}, argument ${i}: ${e.message}`; throw e; } } - let result: { - publicOutput?: any; - auxiliaryOutput?: any; - }; - if (publicInputType === Undefined || publicInputType === Void) { - result = (await func(...finalArgs)) as any; - } else { - let input = fromFieldVars(publicInputType, publicInput); - result = (await func(input, ...finalArgs)) as any; + + let result: { publicOutput?: any; auxiliaryOutput?: any }; + let proofs: DeclaredProof[]; + + try { + if (publicInputType === Undefined || publicInputType === Void) { + result = (await func(...finalArgs)) as any; + } else { + let input = fromFieldVars(publicInputType, publicInput); + result = (await func(input, ...finalArgs)) as any; + } + proofs = ZkProgramContext.getDeclaredProofs(); + } finally { + ZkProgramContext.leave(id); } + // now all proofs are declared - extract their statements for Pickles + let previousStatements = proofs.map( + ({ proof }): Pickles.Statement => { + let fields = proof.publicFields(); + let input = MlFieldArray.to(fields.input); + let output = MlFieldArray.to(fields.output); + return MlPair(input, output); + } + ); + proofs.forEach(({ Proof, proof }) => { if (!(proof instanceof DynamicProof)) return; From 907b202c3518c8ee50bee0ad5cf7ef4ff7b620c6 Mon Sep 17 00:00:00 2001 From: Gregor Date: Thu, 28 Nov 2024 08:27:47 +0100 Subject: [PATCH 216/328] revert unnecessary change and add comments --- src/lib/proof-system/zkprogram.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index a1159dd894..ec928554eb 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -797,7 +797,7 @@ function picklesRuleFromFunction( proofSystemTag: { name: string }, { methodName, args, auxiliaryType }: MethodInterface, gates: Gate[], - state: ReturnType = createProgramState() + state?: ReturnType ): Pickles.Rule { async function main( publicInput: MlFieldArray @@ -805,6 +805,7 @@ function picklesRuleFromFunction( let { witnesses: argsWithoutPublicInput, inProver } = snarkContext.get(); assert(!(inProver && argsWithoutPublicInput === undefined)); + // witness private inputs and declare input proofs let id = ZkProgramContext.enter(); let finalArgs = []; for (let i = 0; i < args.length; i++) { @@ -826,6 +827,7 @@ function picklesRuleFromFunction( } } + // run the user circuit let result: { publicOutput?: any; auxiliaryOutput?: any }; let proofs: DeclaredProof[]; @@ -851,6 +853,7 @@ function picklesRuleFromFunction( } ); + // handle dynamic proofs proofs.forEach(({ Proof, proof }) => { if (!(proof instanceof DynamicProof)) return; @@ -885,7 +888,11 @@ function picklesRuleFromFunction( ? publicOutputType.toFields(result.publicOutput) : []; - if (auxiliaryType !== undefined && auxiliaryType.sizeInFields() !== 0) { + if ( + state !== undefined && + auxiliaryType !== undefined && + auxiliaryType.sizeInFields() !== 0 + ) { Provable.asProver(() => { let { auxiliaryOutput } = result; assert( From 5b6145bbfddc353e32a3878ab6a551ebc4fa9db2 Mon Sep 17 00:00:00 2001 From: Gregor Date: Thu, 28 Nov 2024 09:19:37 +0100 Subject: [PATCH 217/328] add `Proof.declare()` --- src/lib/proof-system/proof.ts | 22 ++++++++++++++++++++++ src/lib/proof-system/zkprogram-context.ts | 1 + src/lib/proof-system/zkprogram.ts | 5 +---- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/lib/proof-system/proof.ts b/src/lib/proof-system/proof.ts index 9111482cf9..1fc4a230fb 100644 --- a/src/lib/proof-system/proof.ts +++ b/src/lib/proof-system/proof.ts @@ -12,6 +12,7 @@ import type { Provable } from '../provable/provable.js'; import { assert } from '../util/assert.js'; import { Unconstrained } from '../provable/types/unconstrained.js'; import { ProvableType } from '../provable/types/provable-intf.js'; +import { ZkProgramContext } from './zkprogram-context.js'; // public API export { ProofBase, Proof, DynamicProof }; @@ -36,6 +37,27 @@ class ProofBase { maxProofsVerified: 0 | 1 | 2; shouldVerify = Bool(false); + /** + * To verify a recursive proof inside a ZkProgram method, it has to be "declared" as part of + * the method. This is done by calling `declare()` on the proof. + * + * Note: `declare()` is a low-level method that most users will not have to call directly. + * For proofs that are inputs to the ZkProgram, it is done automatically. + * + * You can think of declaring a proof as a similar step as witnessing a variable, which introduces + * that variable to the circuit. Declaring a proof will tell Pickles to add the additional constraints + * for recursive proof verification. + * + * Similar to `Provable.witness()`, `declare()` is a no-op when run outside ZkProgram compilation or proving. + * It returns `false` in that case, and `true` if the proof was actually declared. + */ + declare() { + if (!ZkProgramContext.has()) return false; + const Proof = this.constructor as Subclass; + ZkProgramContext.declareProof({ Proof, proof: this }); + return true; + } + toJSON(): JsonProof { let fields = this.publicFields(); return { diff --git a/src/lib/proof-system/zkprogram-context.ts b/src/lib/proof-system/zkprogram-context.ts index 955e61b366..f6b66f6459 100644 --- a/src/lib/proof-system/zkprogram-context.ts +++ b/src/lib/proof-system/zkprogram-context.ts @@ -18,6 +18,7 @@ const ZkProgramContext = { return context.enter({ proofs: [] }); }, leave: context.leave, + has: context.has, declareProof(proof: DeclaredProof) { context.get().proofs.push(proof); diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index ec928554eb..812f9091bf 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -816,10 +816,7 @@ function picklesRuleFromFunction( }); finalArgs[i] = value; - for (let proof of extractProofs(value)) { - let Proof = proof.constructor as Subclass>; - ZkProgramContext.declareProof({ Proof, proof }); - } + extractProofs(value).forEach((proof) => proof.declare()); } catch (e: any) { ZkProgramContext.leave(id); e.message = `Error when witnessing in ${methodName}, argument ${i}: ${e.message}`; From b576a409776fc81e1767f6ac870e21231e0c3441 Mon Sep 17 00:00:00 2001 From: Gregor Date: Thu, 28 Nov 2024 11:19:32 +0100 Subject: [PATCH 218/328] scaffold internal recursive proving feature --- src/lib/proof-system/zkprogram.ts | 130 +++++++++++++++++++----------- src/lib/util/arrays.ts | 23 +++++- 2 files changed, 106 insertions(+), 47 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 812f9091bf..3ad193c4b0 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -54,6 +54,7 @@ import { import { emptyWitness } from '../provable/types/util.js'; import { InferValue } from '../../bindings/lib/provable-generic.js'; import { DeclaredProof, ZkProgramContext } from './zkprogram-context.js'; +import { mapObject, mapToObject } from '../util/arrays.js'; // public API export { @@ -238,6 +239,13 @@ function ZkProgram< rawMethods: { [I in keyof Config['methods']]: Methods[I]['method']; }; + proveRecursively: { + [I in keyof Config['methods']]: RecursiveProver< + InferProvableOrUndefined>, + InferProvableOrVoid>, + PrivateInputs[I] + >; + }; proofsEnabled: boolean; setProofsEnabled(proofsEnabled: boolean): void; } & { @@ -268,12 +276,13 @@ function ZkProgram< static tag = () => selfTag; } + type MethodKey = keyof Config['methods']; // TODO remove sort()! Object.keys() has a deterministic order - let methodKeys: (keyof Methods & string)[] = Object.keys(methods).sort(); // need to have methods in (any) fixed order + let methodKeys: MethodKey[] = Object.keys(methods).sort(); // need to have methods in (any) fixed order let methodIntfs = methodKeys.map((key) => sortMethodArguments( 'program', - key, + key as string, methods[key].privateInputs, ProvableType.get(methods[key].auxiliaryOutput) ?? Undefined, SelfProof @@ -315,7 +324,7 @@ function ZkProgram< async function compile({ cache = Cache.FileSystemDefault, forceRecompile = false, - proofsEnabled = undefined, + proofsEnabled = undefined as boolean | undefined, } = {}) { doProving = proofsEnabled ?? doProving; @@ -345,25 +354,19 @@ function ZkProgram< } } - function toProver( + type RegularProver = ( + publicInput: PublicInput, + ...args: PrivateInputs[K] + ) => Promise<{ + proof: Proof; + auxiliaryOutput: InferProvableOrUndefined; + }>; + + function toRegularProver( key: K, i: number - ): [ - K, - Prover< - PublicInput, - PublicOutput, - PrivateInputs[K], - InferProvableOrUndefined - > - ] { - async function prove_( - publicInput: PublicInput, - ...args: TupleToInstances - ): Promise<{ - proof: Proof; - auxiliaryOutput: any; - }> { + ): RegularProver { + return async function prove_(publicInput, ...args) { class ProgramProof extends Proof { static publicInputType = publicInputType; static publicOutputType = publicOutputType; @@ -388,7 +391,9 @@ function ZkProgram< let picklesProver = compileOutput?.provers?.[i]; if (picklesProver === undefined) { throw Error( - `Cannot prove execution of program.${key}(), no prover found. ` + + `Cannot prove execution of program.${String( + key + )}(), no prover found. ` + `Try calling \`await program.compile()\` first, this will cache provers in the background.\nIf you compiled your zkProgram with proofs disabled (\`proofsEnabled = false\`), you have to compile it with proofs enabled first.` ); } @@ -428,33 +433,27 @@ function ZkProgram< }), auxiliaryOutput, }; - } - - let prove: Prover< - PublicInput, - PublicOutput, - PrivateInputs[K], - InferProvableOrUndefined - >; - if ( - (publicInputType as any) === Undefined || - (publicInputType as any) === Void - ) { - prove = ((...args: any) => prove_(undefined as any, ...args)) as any; - } else { - prove = prove_ as any; - } - return [key, prove]; + }; } + let regularProvers = mapToObject(methodKeys, toRegularProver); - let provers = Object.fromEntries(methodKeys.map(toProver)) as { - [I in keyof Config['methods']]: Prover< - PublicInput, - PublicOutput, - PrivateInputs[I], - InferProvableOrUndefined - >; + type Prover_ = Prover< + PublicInput, + PublicOutput, + PrivateInputs[K], + InferProvableOrUndefined + >; + type Provers = { + [K in MethodKey]: Prover_; }; + let provers: Provers = mapToObject(methodKeys, (key): Prover_ => { + if (publicInputType === Undefined || publicInputType === Void) { + return ((...args: any) => + regularProvers[key](undefined as any, ...args)) as any; + } else { + return regularProvers[key] as any; + } + }); function verify(proof: Proof) { if (!doProving) { @@ -472,6 +471,31 @@ function ZkProgram< return compileOutput.verify(statement, proof.proof); } + let regularRecursiveProvers = mapObject(regularProvers, (prove, key) => { + return async function proveRecursively_( + publicInput: PublicInput | undefined, + ...args: TupleToInstances + ) { + throw Error('todo'); + }; + }); + type RecursiveProver_ = RecursiveProver< + PublicInput, + PublicOutput, + PrivateInputs[K] + >; + type RecursiveProvers = { + [K in MethodKey]: RecursiveProver_; + }; + let proveRecursively: RecursiveProvers = mapToObject(methodKeys, (key) => { + if (publicInputType === Undefined || publicInputType === Void) { + return ((...args: any) => + regularRecursiveProvers[key](undefined, ...args)) as any; + } else { + return regularRecursiveProvers[key] as any; + } + }); + async function digest() { let methodsMeta = await analyzeMethods(); let digests: Field[] = methodKeys.map((k) => @@ -502,9 +526,12 @@ function ZkProgram< rawMethods: Object.fromEntries( methodKeys.map((key) => [key, methods[key].method]) ) as any, + proofsEnabled: doProving, setProofsEnabled(proofsEnabled: boolean) { doProving = proofsEnabled; }, + + proveRecursively, }, provers ); @@ -514,7 +541,7 @@ function ZkProgram< get: () => doProving, }); - return program as any; + return program; } type ZkProgram< @@ -1110,6 +1137,17 @@ type Prover< auxiliaryOutput: AuxiliaryOutput; }>; +type RecursiveProver< + PublicInput, + PublicOutput, + Args extends Tuple +> = PublicInput extends undefined + ? (...args: TupleToInstances) => Promise + : ( + publicInput: PublicInput, + ...args: TupleToInstances + ) => Promise; + type ProvableOrUndefined = A extends undefined ? typeof Undefined : ToProvable; diff --git a/src/lib/util/arrays.ts b/src/lib/util/arrays.ts index b8d11660f3..b62440ab2a 100644 --- a/src/lib/util/arrays.ts +++ b/src/lib/util/arrays.ts @@ -1,6 +1,6 @@ import { assert } from './errors.js'; -export { chunk, chunkString, zip, pad }; +export { chunk, chunkString, zip, pad, mapObject, mapToObject }; function chunk(array: T[], size: number): T[][] { assert( @@ -31,3 +31,24 @@ function pad(array: T[], size: number, value: T): T[] { ); return array.concat(Array.from({ length: size - array.length }, () => value)); } + +function mapObject< + T extends Record, + F extends (value: T[K], key: K) => any +>(t: T, fn: F) { + let s = {} as { [K in keyof T]: ReturnType }; + for (let key in t) { + s[key] = fn(t[key], key); + } + return s; +} +function mapToObject< + Key extends string | number | symbol, + F extends (key: K, i: number) => any +>(keys: Key[], fn: F) { + let s = {} as { [K in Key]: ReturnType }; + keys.forEach((key, i) => { + s[key] = fn(key, i); + }); + return s; +} From 0f9b59e9181efcaf59d77bb14537603c981fa41e Mon Sep 17 00:00:00 2001 From: Gregor Date: Thu, 28 Nov 2024 11:38:04 +0100 Subject: [PATCH 219/328] implement recursive proving --- src/lib/proof-system/zkprogram.ts | 33 ++++++++++++++++--------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 3ad193c4b0..59a194a4d4 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -367,12 +367,6 @@ function ZkProgram< i: number ): RegularProver { return async function prove_(publicInput, ...args) { - class ProgramProof extends Proof { - static publicInputType = publicInputType; - static publicOutputType = publicOutputType; - static tag = () => selfTag; - } - if (!doProving) { let previousProofs = MlArray.to(getPreviousProofsForProver(args)); @@ -380,7 +374,7 @@ function ZkProgram< (await (methods[key].method as any)(publicInput, previousProofs)) ?? {}; - let proof = await ProgramProof.dummy( + let proof = await SelfProof.dummy( publicInput, publicOutput, maxProofsVerified @@ -425,7 +419,7 @@ function ZkProgram< let publicOutput = fromFieldConsts(publicOutputType, publicOutputFields); return { - proof: new ProgramProof({ + proof: new SelfProof({ publicInput, publicOutput, proof, @@ -446,12 +440,11 @@ function ZkProgram< type Provers = { [K in MethodKey]: Prover_; }; - let provers: Provers = mapToObject(methodKeys, (key): Prover_ => { + let provers: Provers = mapObject(regularProvers, (prover): Prover_ => { if (publicInputType === Undefined || publicInputType === Void) { - return ((...args: any) => - regularProvers[key](undefined as any, ...args)) as any; + return ((...args: any) => prover(undefined as any, ...args)) as any; } else { - return regularProvers[key] as any; + return prover as any; } }); @@ -471,12 +464,20 @@ function ZkProgram< return compileOutput.verify(statement, proof.proof); } - let regularRecursiveProvers = mapObject(regularProvers, (prove, key) => { + let regularRecursiveProvers = mapObject(regularProvers, (prover) => { return async function proveRecursively_( - publicInput: PublicInput | undefined, + publicInput: PublicInput, ...args: TupleToInstances ) { - throw Error('todo'); + // create the base proof in a witness block + let proof = await Provable.witnessAsync(SelfProof, async () => { + let { proof } = await prover(publicInput, ...(args as any)); + return proof; + }); + // declare and verify the proof, and return its public output + proof.declare(); + proof.verify(); + return proof.publicOutput; }; }); type RecursiveProver_ = RecursiveProver< @@ -490,7 +491,7 @@ function ZkProgram< let proveRecursively: RecursiveProvers = mapToObject(methodKeys, (key) => { if (publicInputType === Undefined || publicInputType === Void) { return ((...args: any) => - regularRecursiveProvers[key](undefined, ...args)) as any; + regularRecursiveProvers[key](undefined as any, ...args)) as any; } else { return regularRecursiveProvers[key] as any; } From 529214216e5bfad8ffd4e5ac2261fee192c6bbbd Mon Sep 17 00:00:00 2001 From: Gregor Date: Thu, 28 Nov 2024 11:38:21 +0100 Subject: [PATCH 220/328] add tests --- src/tests/fake-proof.ts | 45 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/src/tests/fake-proof.ts b/src/tests/fake-proof.ts index 46f76121a1..969d7c79f0 100644 --- a/src/tests/fake-proof.ts +++ b/src/tests/fake-proof.ts @@ -12,14 +12,19 @@ import { } from 'o1js'; import assert from 'assert'; +let callRecursive = () => {}; + const RealProgram = ZkProgram({ name: 'real', + publicOutput: UInt64, methods: { make: { privateInputs: [UInt64], async method(value: UInt64) { + callRecursive(); let expected = UInt64.from(34); value.assertEquals(expected); + return { publicOutput: value.add(1) }; }, }, }, @@ -27,13 +32,19 @@ const RealProgram = ZkProgram({ const FakeProgram = ZkProgram({ name: 'fake', + publicOutput: UInt64, methods: { - make: { privateInputs: [UInt64], async method(_: UInt64) {} }, + make: { + privateInputs: [UInt64], + async method(_: UInt64) { + return { publicOutput: UInt64.zero }; + }, + }, }, }); class RealProof extends ZkProgram.Proof(RealProgram) {} -const Nested = Struct({ inner: RealProof }); +class Nested extends Struct({ inner: RealProof }) {} const RecursiveProgram = ZkProgram({ name: 'recursive', @@ -46,11 +57,18 @@ const RecursiveProgram = ZkProgram({ }, verifyNested: { privateInputs: [Field, Nested], - async method(_unrelated, { inner }) { - inner satisfies Proof; + async method(_unrelated, { inner }: Nested) { + inner satisfies Proof; inner.verify(); }, }, + verifyInternal: { + privateInputs: [], + async method() { + let x = await RealProgram.proveRecursively.make(UInt64.from(34)); + x.assertEquals(UInt64.from(35)); + }, + }, }, }); @@ -71,7 +89,7 @@ let { verificationKey: programVk } = await RecursiveProgram.compile(); // proof that should be rejected const { proof: fakeProof } = await FakeProgram.make(UInt64.from(99999)); -const dummyProof = await RealProof.dummy(undefined, undefined, 0); +const dummyProof = await RealProof.dummy(undefined, UInt64.zero, 0); for (let proof of [fakeProof, dummyProof]) { // zkprogram rejects proof @@ -127,3 +145,20 @@ assert( ); console.log('fake proof test passed for nested proofs 🎉'); + +// test internal proof + +let wasCalled = false; +callRecursive = () => { + console.log('creating a proof inside another!!!'); + wasCalled = true; +}; + +const { proof: internalProof } = await RecursiveProgram.verifyInternal(); +assert( + await verify(internalProof, programVk), + 'recursive program accepts internal proof' +); +assert(wasCalled, 'other program was called'); + +console.log('positive test passed for internal proofs 🎉'); From 9220094681b79e0a128cf1e8f7775557625e38e8 Mon Sep 17 00:00:00 2001 From: Gregor Date: Thu, 28 Nov 2024 11:39:04 +0100 Subject: [PATCH 221/328] simplify test --- src/tests/fake-proof.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/tests/fake-proof.ts b/src/tests/fake-proof.ts index 969d7c79f0..5cc2338bfb 100644 --- a/src/tests/fake-proof.ts +++ b/src/tests/fake-proof.ts @@ -148,17 +148,12 @@ console.log('fake proof test passed for nested proofs 🎉'); // test internal proof -let wasCalled = false; -callRecursive = () => { - console.log('creating a proof inside another!!!'); - wasCalled = true; -}; +callRecursive = () => console.log('creating a proof inside another!!!'); const { proof: internalProof } = await RecursiveProgram.verifyInternal(); assert( await verify(internalProof, programVk), 'recursive program accepts internal proof' ); -assert(wasCalled, 'other program was called'); console.log('positive test passed for internal proofs 🎉'); From 0a865fa790b94ad7cb1041d2f86ca5eb70d1fe44 Mon Sep 17 00:00:00 2001 From: Gregor Date: Thu, 28 Nov 2024 11:52:53 +0100 Subject: [PATCH 222/328] check whether bindings are intitialized to throw a better error --- src/lib/proof-system/proof.ts | 15 ++++++++++++++- src/snarky.d.ts | 3 +++ src/snarky.js | 1 + src/snarky.web.js | 1 + 4 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/lib/proof-system/proof.ts b/src/lib/proof-system/proof.ts index 95f60a2e0f..1b5d6d0f49 100644 --- a/src/lib/proof-system/proof.ts +++ b/src/lib/proof-system/proof.ts @@ -1,4 +1,8 @@ -import { initializeBindings, withThreadPool } from '../../snarky.js'; +import { + areBindingsInitialized, + initializeBindings, + withThreadPool, +} from '../../snarky.js'; import { Pickles } from '../../snarky.js'; import { Field, Bool } from '../provable/wrapped.js'; import type { @@ -94,9 +98,11 @@ class ProofBase { } static _proofFromBase64(proofString: string, maxProofsVerified: 0 | 1 | 2) { + assertBindingsInitialized(); return Pickles.proofOfBase64(proofString, maxProofsVerified)[1]; } static _proofToBase64(proof: Pickles.Proof, maxProofsVerified: 0 | 1 | 2) { + assertBindingsInitialized(); return Pickles.proofToBase64([maxProofsVerified, proof]); } } @@ -435,3 +441,10 @@ function extractProofTypes(type: ProvableType) { let proofValues = extractProofs(value); return proofValues.map((proof) => proof.constructor as typeof ProofBase); } + +function assertBindingsInitialized() { + assert( + areBindingsInitialized, + 'Bindings are not initialized. Try calling `await initializeBindings()` first.' + ); +} diff --git a/src/snarky.d.ts b/src/snarky.d.ts index 5f46056cf4..9b91a2de62 100644 --- a/src/snarky.d.ts +++ b/src/snarky.d.ts @@ -47,8 +47,11 @@ export { MlPublicKey, MlPublicKeyVar, MlFeatureFlags, + areBindingsInitialized, }; +declare let areBindingsInitialized: boolean; + type WasmModule = typeof wasm; type MlGroup = MlPair; diff --git a/src/snarky.js b/src/snarky.js index 1ffe22a191..70d5aff20a 100644 --- a/src/snarky.js +++ b/src/snarky.js @@ -33,4 +33,5 @@ export { withThreadPool, wasm, initializeBindings, + isInitialized as areBindingsInitialized, }; diff --git a/src/snarky.web.js b/src/snarky.web.js index c5bdf2725f..95752ea05c 100644 --- a/src/snarky.web.js +++ b/src/snarky.web.js @@ -29,4 +29,5 @@ export { withThreadPool, wasm, initializeBindings, + isInitialized as areBindingsInitialized, }; From 577d5e7c2f60024d0646ada005b9a0748537c414 Mon Sep 17 00:00:00 2001 From: Gregor Date: Thu, 28 Nov 2024 11:53:25 +0100 Subject: [PATCH 223/328] add test --- src/lib/proof-system/proof.unit-test.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/lib/proof-system/proof.unit-test.ts b/src/lib/proof-system/proof.unit-test.ts index f48c7519d6..ba3f3148ad 100644 --- a/src/lib/proof-system/proof.unit-test.ts +++ b/src/lib/proof-system/proof.unit-test.ts @@ -13,8 +13,19 @@ test('Proof provable', async () => { expect(MyProof.provable.sizeInFields()).toEqual(1); + // can't call this before bindings are initialized + expect(() => MyProof._proofFromBase64('', 0)).toThrow( + 'Bindings are not initialized' + ); + let proof = await MyProof.dummy(Field(1n), undefined, 0); + // now bindings are initialized and we can call this + let proofBase64 = MyProof._proofToBase64(proof.proof, 0); + let proofRecovered = MyProof._proofFromBase64(proofBase64, 0); + let proofBase64_2 = MyProof._proofToBase64(proofRecovered, 0); + expect(proofBase64).toEqual(proofBase64_2); + expect(MyProof.provable.toFields(proof)).toEqual([Field(1n)]); expect(MyProof.provable.toAuxiliary(proof)).toEqual([ [], From 2250126e74d2b07a93bb77efa603bdde8520b29a Mon Sep 17 00:00:00 2001 From: Gregor Date: Thu, 28 Nov 2024 12:29:58 +0100 Subject: [PATCH 224/328] add test for internal proofs --- src/tests/inductive-proofs-internal.ts | 62 ++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 src/tests/inductive-proofs-internal.ts diff --git a/src/tests/inductive-proofs-internal.ts b/src/tests/inductive-proofs-internal.ts new file mode 100644 index 0000000000..bfb365c1de --- /dev/null +++ b/src/tests/inductive-proofs-internal.ts @@ -0,0 +1,62 @@ +import { Field, ZkProgram, assert, Provable } from 'o1js'; +import { tic, toc } from '../examples/utils/tic-toc.js'; +import { expect } from 'expect'; + +let log: string[] = []; + +function pushLog(s: string) { + Provable.asProver(() => { + console.log(s); + log.push(s); + }); +} + +let MaxProofsVerifiedTwo = ZkProgram({ + name: 'recursive-2', + publicOutput: Field, + + methods: { + baseCase: { + privateInputs: [], + + async method() { + pushLog('baseCase'); + return { publicOutput: Field(7) }; + }, + }, + + mergeOne: { + privateInputs: [], + + async method() { + pushLog('mergeOne'); + let x: Field = await MaxProofsVerifiedTwo.proveRecursively.baseCase(); + return { publicOutput: x.add(1) }; + }, + }, + + mergeTwo: { + privateInputs: [], + + async method() { + pushLog('mergeTwo'); + let x: Field = await MaxProofsVerifiedTwo.proveRecursively.baseCase(); + let y: Field = await MaxProofsVerifiedTwo.proveRecursively.mergeOne(); + return { publicOutput: x.add(y) }; + }, + }, + }, +}); +tic('compiling'); +await MaxProofsVerifiedTwo.compile(); +toc(); + +tic('executing 4 proofs'); +let { proof } = await MaxProofsVerifiedTwo.mergeTwo(); +toc(); + +assert(await MaxProofsVerifiedTwo.verify(proof), 'Proof is not valid'); + +proof.publicOutput.assertEquals(15); + +expect(log).toEqual(['mergeTwo', 'baseCase', 'mergeOne', 'baseCase']); From afbbf93eef1350726cde59053b1ffbe7808112e4 Mon Sep 17 00:00:00 2001 From: Gregor Date: Thu, 28 Nov 2024 12:31:04 +0100 Subject: [PATCH 225/328] add test to CI --- run-ci-tests.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/run-ci-tests.sh b/run-ci-tests.sh index c4aa4a133d..a75277d8b9 100755 --- a/run-ci-tests.sh +++ b/run-ci-tests.sh @@ -9,6 +9,7 @@ case $TEST_TYPE in ./run src/examples/zkapps/reducer/reducer-composite.ts --bundle ./run src/examples/zkapps/composability.ts --bundle ./run src/tests/fake-proof.ts + ./run src/tests/inductive-proofs-internal.ts --bundle ./run tests/vk-regression/diverse-zk-program-run.ts --bundle ;; From 258268e26a1f0393f2ec3db8c94555b4e8badc7f Mon Sep 17 00:00:00 2001 From: Gregor Date: Thu, 28 Nov 2024 13:22:00 +0100 Subject: [PATCH 226/328] move withThreadPool to common file --- src/lib/proof-system/workers.ts | 67 ++++++++++++++++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) diff --git a/src/lib/proof-system/workers.ts b/src/lib/proof-system/workers.ts index 9076ad7554..cff25a58bf 100644 --- a/src/lib/proof-system/workers.ts +++ b/src/lib/proof-system/workers.ts @@ -1,4 +1,4 @@ -export { workers, setNumberOfWorkers }; +export { workers, setNumberOfWorkers, WithThreadPool }; const workers = { numWorkers: undefined as number | undefined, @@ -15,3 +15,68 @@ const workers = { const setNumberOfWorkers = (numWorkers: number) => { workers.numWorkers = numWorkers; }; + +type ThreadPoolState = + | { type: 'none' } + | { type: 'initializing'; initPromise: Promise } + | { type: 'running' } + | { type: 'exiting'; exitPromise: Promise }; + +function WithThreadPool({ + initThreadPool, + exitThreadPool, +}: { + initThreadPool: () => Promise; + exitThreadPool: () => Promise; +}) { + // state machine to enable calling multiple functions that need a thread pool at once + let state: ThreadPoolState = { type: 'none' }; + let isNeededBy = 0; + + return async function withThreadPool(run: () => Promise): Promise { + isNeededBy++; + // none, exiting -> initializing + switch (state.type) { + case 'none': { + let initPromise = initThreadPool(); + state = { type: 'initializing', initPromise }; + break; + } + case 'initializing': + case 'running': + break; + case 'exiting': { + let initPromise = state.exitPromise.then(initThreadPool); + state = { type: 'initializing', initPromise }; + break; + } + } + // initializing -> running + if (state.type === 'initializing') await state.initPromise; + state = { type: 'running' }; + + let result: T; + try { + result = await run(); + } finally { + // running -> exiting IF we don't need to run longer + isNeededBy--; + + if (state.type !== 'running') { + throw Error('bug in ThreadPool state machine'); + } + + if (isNeededBy < 1) { + let exitPromise = exitThreadPool(); + state = { type: 'exiting', exitPromise }; + + // exiting -> none IF we didn't move exiting -> initializing + await exitPromise; + if (state.type === 'exiting') { + state = { type: 'none' }; + } + } + } + return result; + }; +} From dbebf51a93a8a7c8a391812ceaa94107a0cf5b55 Mon Sep 17 00:00:00 2001 From: Gregor Date: Thu, 28 Nov 2024 13:22:19 +0100 Subject: [PATCH 227/328] allow test to run in web --- src/tests/inductive-proofs-internal.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/tests/inductive-proofs-internal.ts b/src/tests/inductive-proofs-internal.ts index bfb365c1de..7867acedce 100644 --- a/src/tests/inductive-proofs-internal.ts +++ b/src/tests/inductive-proofs-internal.ts @@ -1,6 +1,5 @@ import { Field, ZkProgram, assert, Provable } from 'o1js'; import { tic, toc } from '../examples/utils/tic-toc.js'; -import { expect } from 'expect'; let log: string[] = []; @@ -59,4 +58,8 @@ assert(await MaxProofsVerifiedTwo.verify(proof), 'Proof is not valid'); proof.publicOutput.assertEquals(15); -expect(log).toEqual(['mergeTwo', 'baseCase', 'mergeOne', 'baseCase']); +assert(log.length === 4, 'log.length === 4'); +assert(log[0] === 'mergeTwo', 'log[0] === "mergeTwo"'); +assert(log[1] === 'baseCase', 'log[1] === "baseCase"'); +assert(log[2] === 'mergeOne', 'log[2] === "mergeOne"'); +assert(log[3] === 'baseCase', 'log[3] === "baseCase"'); From 2738b592bf7d06c56f6b2899e97257ed4d152175 Mon Sep 17 00:00:00 2001 From: Gregor Date: Thu, 28 Nov 2024 13:22:50 +0100 Subject: [PATCH 228/328] bindings --- src/bindings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bindings b/src/bindings index 2c62a9a755..d6509b9fd0 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit 2c62a9a755f1b128f89cc2131814df7157f68109 +Subproject commit d6509b9fd082785ef33eefc3c565ab5e9551dacb From e6b4e5467c7d13a820020c5073f9ea312968d0d1 Mon Sep 17 00:00:00 2001 From: Gregor Date: Thu, 28 Nov 2024 13:29:46 +0100 Subject: [PATCH 229/328] changelog --- CHANGELOG.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 48876c95f6..2fba42f983 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,10 +17,15 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ## [Unreleased](https://github.com/o1-labs/o1js/compare/e1bac02...HEAD) +### Added + +- API for recursively proving a ZkProgram method from within another https://github.com/o1-labs/o1js/pull/1931 + - `program.proveRecursively.(...args): Promise` + - This also works within the same program, as long as the return value is type-annotated + ### Fixed - Compiling stuck in the browser for recursive zkprograms https://github.com/o1-labs/o1js/pull/1906 - - Error message in `rangeCheck16` gadget https://github.com/o1-labs/o1js/pull/1920 ## [2.1.0](https://github.com/o1-labs/o1js/compare/b04520d...e1bac02) - 2024-11-13 From 3289b6badb6fa6fd1357f1a3d7e893c56b66f9d6 Mon Sep 17 00:00:00 2001 From: Gregor Date: Thu, 28 Nov 2024 14:09:18 +0100 Subject: [PATCH 230/328] properly constrain public input, and map inner args to constants --- src/lib/proof-system/zkprogram.ts | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 59a194a4d4..2cb0222b3b 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -54,7 +54,7 @@ import { import { emptyWitness } from '../provable/types/util.js'; import { InferValue } from '../../bindings/lib/provable-generic.js'; import { DeclaredProof, ZkProgramContext } from './zkprogram-context.js'; -import { mapObject, mapToObject } from '../util/arrays.js'; +import { mapObject, mapToObject, zip } from '../util/arrays.js'; // public API export { @@ -262,6 +262,8 @@ function ZkProgram< let publicInputType: ProvablePure = ProvableType.get( config.publicInput ?? Undefined ); + let hasPublicInput = + publicInputType !== Undefined && publicInputType !== Void; let publicOutputType: ProvablePure = ProvableType.get( config.publicOutput ?? Void ); @@ -464,16 +466,27 @@ function ZkProgram< return compileOutput.verify(statement, proof.proof); } - let regularRecursiveProvers = mapObject(regularProvers, (prover) => { + let regularRecursiveProvers = mapObject(regularProvers, (prover, key) => { return async function proveRecursively_( publicInput: PublicInput, ...args: TupleToInstances ) { // create the base proof in a witness block let proof = await Provable.witnessAsync(SelfProof, async () => { - let { proof } = await prover(publicInput, ...(args as any)); + // move method args to constants + let constInput = Provable.toConstant(publicInputType, publicInput); + let constArgs = zip(args, methods[key].privateInputs).map( + ([arg, type]) => Provable.toConstant(type, arg) + ); + let { proof } = await prover(constInput, ...(constArgs as any)); return proof; }); + + // assert that the witnessed proof has the correct public input (which will be used by Pickles as part of verification) + if (hasPublicInput) { + Provable.assertEqual(publicInputType, proof.publicInput, publicInput); + } + // declare and verify the proof, and return its public output proof.declare(); proof.verify(); From 00a1c69aa0b143ccb8f23a22b4d1ef1a837d755f Mon Sep 17 00:00:00 2001 From: Gregor Date: Thu, 28 Nov 2024 14:09:29 +0100 Subject: [PATCH 231/328] test witness arguments --- src/tests/inductive-proofs-internal.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/tests/inductive-proofs-internal.ts b/src/tests/inductive-proofs-internal.ts index 7867acedce..7d528fe805 100644 --- a/src/tests/inductive-proofs-internal.ts +++ b/src/tests/inductive-proofs-internal.ts @@ -16,11 +16,12 @@ let MaxProofsVerifiedTwo = ZkProgram({ methods: { baseCase: { - privateInputs: [], + privateInputs: [Field], - async method() { + async method(x: Field) { pushLog('baseCase'); - return { publicOutput: Field(7) }; + x = x.add(7); + return { publicOutput: x }; }, }, @@ -29,7 +30,8 @@ let MaxProofsVerifiedTwo = ZkProgram({ async method() { pushLog('mergeOne'); - let x: Field = await MaxProofsVerifiedTwo.proveRecursively.baseCase(); + let z = Provable.witness(Field, () => 0); + let x: Field = await MaxProofsVerifiedTwo.proveRecursively.baseCase(z); return { publicOutput: x.add(1) }; }, }, @@ -39,7 +41,8 @@ let MaxProofsVerifiedTwo = ZkProgram({ async method() { pushLog('mergeTwo'); - let x: Field = await MaxProofsVerifiedTwo.proveRecursively.baseCase(); + let z = Provable.witness(Field, () => 0); + let x: Field = await MaxProofsVerifiedTwo.proveRecursively.baseCase(z); let y: Field = await MaxProofsVerifiedTwo.proveRecursively.mergeOne(); return { publicOutput: x.add(y) }; }, From a89c8cd37a230a191526778d89e21b8ec9fc4f54 Mon Sep 17 00:00:00 2001 From: Gregor Date: Thu, 28 Nov 2024 16:31:38 +0100 Subject: [PATCH 232/328] implement conditional recursion --- src/lib/proof-system/zkprogram.ts | 100 +++++++++++++++++++++++++----- 1 file changed, 86 insertions(+), 14 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 2cb0222b3b..9c88ac64e2 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -55,6 +55,7 @@ import { emptyWitness } from '../provable/types/util.js'; import { InferValue } from '../../bindings/lib/provable-generic.js'; import { DeclaredProof, ZkProgramContext } from './zkprogram-context.js'; import { mapObject, mapToObject, zip } from '../util/arrays.js'; +import { Bool } from '../provable/bool.js'; // public API export { @@ -246,6 +247,13 @@ function ZkProgram< PrivateInputs[I] >; }; + proveRecursivelyIf: { + [I in keyof Config['methods']]: ConditionalRecursiveProver< + InferProvableOrUndefined>, + InferProvableOrVoid>, + PrivateInputs[I] + >; + }; proofsEnabled: boolean; setProofsEnabled(proofsEnabled: boolean): void; } & { @@ -468,11 +476,30 @@ function ZkProgram< let regularRecursiveProvers = mapObject(regularProvers, (prover, key) => { return async function proveRecursively_( + conditionAndConfig: Bool | { condition: Bool; domainLog2?: number }, publicInput: PublicInput, ...args: TupleToInstances ) { + let condition = + conditionAndConfig instanceof Bool + ? conditionAndConfig + : conditionAndConfig.condition; + // create the base proof in a witness block let proof = await Provable.witnessAsync(SelfProof, async () => { + let cond = condition.toBoolean(); + if (!cond) { + let publicOutput = ProvableType.synthesize(publicOutputType); + return SelfProof.dummy( + publicInput, + publicOutput, + maxProofsVerified, + conditionAndConfig instanceof Bool + ? undefined + : conditionAndConfig.domainLog2 + ); + } + // move method args to constants let constInput = Provable.toConstant(publicInputType, publicInput); let constArgs = zip(args, methods[key].privateInputs).map( @@ -489,26 +516,55 @@ function ZkProgram< // declare and verify the proof, and return its public output proof.declare(); - proof.verify(); + proof.verifyIf(condition); return proof.publicOutput; }; }); - type RecursiveProver_ = RecursiveProver< - PublicInput, - PublicOutput, - PrivateInputs[K] - >; + type RecursiveProvers = { - [K in MethodKey]: RecursiveProver_; + [K in MethodKey]: RecursiveProver< + PublicInput, + PublicOutput, + PrivateInputs[K] + >; }; - let proveRecursively: RecursiveProvers = mapToObject(methodKeys, (key) => { - if (publicInputType === Undefined || publicInputType === Void) { - return ((...args: any) => - regularRecursiveProvers[key](undefined as any, ...args)) as any; - } else { - return regularRecursiveProvers[key] as any; + type ConditionalRecursiveProvers = { + [K in MethodKey]: ConditionalRecursiveProver< + PublicInput, + PublicOutput, + PrivateInputs[K] + >; + }; + + let proveRecursively: RecursiveProvers = mapObject( + regularRecursiveProvers, + (prover): RecursiveProvers[MethodKey] => { + if (!hasPublicInput) { + return ((...args: any) => + prover(new Bool(true), undefined as any, ...args)) as any; + } else { + return ((pi: PublicInput, ...args: any) => + prover(new Bool(true), pi, ...args)) as any; + } } - }); + ); + let proveRecursivelyIf: ConditionalRecursiveProvers = mapObject( + regularRecursiveProvers, + (prover): ConditionalRecursiveProvers[MethodKey] => { + if (!hasPublicInput) { + return (( + condition: Bool | { condition: Bool; domainLog2?: number }, + ...args: any + ) => prover(condition, undefined as any, ...args)) as any; + } else { + return (( + condition: Bool | { condition: Bool; domainLog2?: number }, + pi: PublicInput, + ...args: any + ) => prover(condition, pi, ...args)) as any; + } + } + ); async function digest() { let methodsMeta = await analyzeMethods(); @@ -546,6 +602,7 @@ function ZkProgram< }, proveRecursively, + proveRecursivelyIf, }, provers ); @@ -1162,6 +1219,21 @@ type RecursiveProver< ...args: TupleToInstances ) => Promise; +type ConditionalRecursiveProver< + PublicInput, + PublicOutput, + Args extends Tuple +> = PublicInput extends undefined + ? ( + condition: Bool | { condition: Bool; domainLog2?: number }, + ...args: TupleToInstances + ) => Promise + : ( + condition: Bool | { condition: Bool; domainLog2?: number }, + publicInput: PublicInput, + ...args: TupleToInstances + ) => Promise; + type ProvableOrUndefined = A extends undefined ? typeof Undefined : ToProvable; From 4a902400f8b8bde106b9f08595962e9a7f8c0fcf Mon Sep 17 00:00:00 2001 From: Gregor Date: Thu, 28 Nov 2024 16:32:49 +0100 Subject: [PATCH 233/328] self-recursive hash chain example --- src/examples/zkprogram/hash-chain.ts | 59 ++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 src/examples/zkprogram/hash-chain.ts diff --git a/src/examples/zkprogram/hash-chain.ts b/src/examples/zkprogram/hash-chain.ts new file mode 100644 index 0000000000..3032e90076 --- /dev/null +++ b/src/examples/zkprogram/hash-chain.ts @@ -0,0 +1,59 @@ +/** + * This shows how to prove a preimage of an arbitrarily long chain of hashes using ZkProgram, i.e. + * "I know x such that hash^n(x) = y". + * + * We implement this as a self-recursive ZkProgram, using `proveRecursivelyIf()` + */ +import { assert, Bool, Field, Poseidon, Provable, ZkProgram } from 'o1js'; + +const HASHES_PER_PROOF = 30; + +const hashChain = ZkProgram({ + name: 'hash-chain', + publicInput: Field, + publicOutput: Field, + + methods: { + chain: { + privateInputs: [Field], + + async method(x: Field, n: Field) { + Provable.log('hashChain (start method)', n); + let y = x; + let k = Field(0); + let reachedN = Bool(false); + + for (let i = 0; i < HASHES_PER_PROOF; i++) { + reachedN = k.equals(n); + y = Provable.if(reachedN, y, Poseidon.hash([y])); + k = Provable.if(reachedN, n, k.add(1)); + } + + // we have y = hash^k(x) + // now do z = hash^(n-k)(y) = hash^n(x) by calling this method recursively + // except if we have k = n, then ignore the output and use y + let z: Field = await hashChain.proveRecursivelyIf.chain( + reachedN.not(), + y, + n.sub(k) + ); + z = Provable.if(reachedN, y, z); + Provable.log('hashChain (start proving)', n); + return { publicOutput: z }; + }, + }, + }, +}); + +await hashChain.compile(); + +let n = 100; +let x = Field.random(); + +let { proof } = await hashChain.chain(x, Field(n)); + +assert(await hashChain.verify(proof), 'Proof invalid'); + +// check that the output is correct +let z = Array.from({ length: n }, () => 0).reduce((y) => Poseidon.hash([y]), x); +proof.publicOutput.assertEquals(z, 'Output is incorrect'); From aa90a40ef207d143cc08693e36f1cd8d4201d674 Mon Sep 17 00:00:00 2001 From: Gregor Date: Thu, 28 Nov 2024 16:43:50 +0100 Subject: [PATCH 234/328] changelog --- CHANGELOG.md | 3 ++- src/examples/zkprogram/hash-chain.ts | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 159d68defb..bc1747b58c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,8 +19,9 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ### Added -- API for recursively proving a ZkProgram method from within another https://github.com/o1-labs/o1js/pull/1931 +- APIs for recursively proving a ZkProgram method from within another https://github.com/o1-labs/o1js/pull/1931 https://github.com/o1-labs/o1js/pull/1932 - `program.proveRecursively.(...args): Promise` + - `program.proveRecursivelyIf.(condition, ...args): Promise` - This also works within the same program, as long as the return value is type-annotated - Add `enforceTransactionLimits` parameter on Network https://github.com/o1-labs/o1js/issues/1910 - Method for optional types to assert none https://github.com/o1-labs/o1js/pull/1922 diff --git a/src/examples/zkprogram/hash-chain.ts b/src/examples/zkprogram/hash-chain.ts index 3032e90076..28071db53d 100644 --- a/src/examples/zkprogram/hash-chain.ts +++ b/src/examples/zkprogram/hash-chain.ts @@ -57,3 +57,5 @@ assert(await hashChain.verify(proof), 'Proof invalid'); // check that the output is correct let z = Array.from({ length: n }, () => 0).reduce((y) => Poseidon.hash([y]), x); proof.publicOutput.assertEquals(z, 'Output is incorrect'); + +console.log('Finished hash chain proof'); From 72eba8a1850c18944507781cdec0d3754ad45edb Mon Sep 17 00:00:00 2001 From: Gregor Date: Thu, 28 Nov 2024 16:57:20 +0100 Subject: [PATCH 235/328] make n also a public input --- src/examples/zkprogram/hash-chain.ts | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/examples/zkprogram/hash-chain.ts b/src/examples/zkprogram/hash-chain.ts index 28071db53d..b009602e38 100644 --- a/src/examples/zkprogram/hash-chain.ts +++ b/src/examples/zkprogram/hash-chain.ts @@ -1,23 +1,33 @@ /** - * This shows how to prove a preimage of an arbitrarily long chain of hashes using ZkProgram, i.e. - * "I know x such that hash^n(x) = y". + * This shows how to prove an arbitrarily long chain of hashes using ZkProgram, i.e. + * `hash^n(x) = y`. * * We implement this as a self-recursive ZkProgram, using `proveRecursivelyIf()` */ -import { assert, Bool, Field, Poseidon, Provable, ZkProgram } from 'o1js'; +import { + assert, + Bool, + Field, + Poseidon, + Provable, + Struct, + ZkProgram, +} from 'o1js'; const HASHES_PER_PROOF = 30; +class HashChainSpec extends Struct({ x: Field, n: Field }) {} + const hashChain = ZkProgram({ name: 'hash-chain', - publicInput: Field, + publicInput: HashChainSpec, publicOutput: Field, methods: { chain: { - privateInputs: [Field], + privateInputs: [], - async method(x: Field, n: Field) { + async method({ x, n }: HashChainSpec) { Provable.log('hashChain (start method)', n); let y = x; let k = Field(0); @@ -34,8 +44,7 @@ const hashChain = ZkProgram({ // except if we have k = n, then ignore the output and use y let z: Field = await hashChain.proveRecursivelyIf.chain( reachedN.not(), - y, - n.sub(k) + { x: y, n: n.sub(k) } ); z = Provable.if(reachedN, y, z); Provable.log('hashChain (start proving)', n); @@ -50,7 +59,7 @@ await hashChain.compile(); let n = 100; let x = Field.random(); -let { proof } = await hashChain.chain(x, Field(n)); +let { proof } = await hashChain.chain({ x, n: Field(n) }); assert(await hashChain.verify(proof), 'Proof invalid'); From d24e1d0a07aa2901b3074e9fd946d3960652e782 Mon Sep 17 00:00:00 2001 From: Gregor Date: Fri, 29 Nov 2024 08:39:08 +0100 Subject: [PATCH 236/328] expose max proofs verified --- src/lib/proof-system/zkprogram.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 2cb0222b3b..6e52fe8d24 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -213,6 +213,8 @@ function ZkProgram< } ): { name: string; + maxProofsVerified(): Promise<0 | 1 | 2>; + compile: (options?: { cache?: Cache; forceRecompile?: boolean; @@ -232,6 +234,7 @@ function ZkProgram< ReturnType >; }>; + publicInputType: ProvableOrUndefined>; publicOutputType: ProvableOrVoid>; privateInputTypes: PrivateInputs; @@ -246,6 +249,7 @@ function ZkProgram< PrivateInputs[I] >; }; + proofsEnabled: boolean; setProofsEnabled(proofsEnabled: boolean): void; } & { @@ -521,10 +525,15 @@ function ZkProgram< const program = Object.assign( selfTag, { + async maxProofsVerified() { + return maxProofsVerified; + }, + compile, verify, digest, analyzeMethods, + publicInputType: publicInputType as ProvableOrUndefined< Get >, @@ -540,6 +549,7 @@ function ZkProgram< rawMethods: Object.fromEntries( methodKeys.map((key) => [key, methods[key].method]) ) as any, + proofsEnabled: doProving, setProofsEnabled(proofsEnabled: boolean) { doProving = proofsEnabled; From 2619a07c3583687871ee959b9ebc91838451d3aa Mon Sep 17 00:00:00 2001 From: Gregor Date: Fri, 29 Nov 2024 08:39:20 +0100 Subject: [PATCH 237/328] fix zkprogram test --- src/tests/inductive-proofs.ts | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/tests/inductive-proofs.ts b/src/tests/inductive-proofs.ts index ebf22754f5..7102eae5c0 100644 --- a/src/tests/inductive-proofs.ts +++ b/src/tests/inductive-proofs.ts @@ -1,5 +1,5 @@ -import { SelfProof, Field, ZkProgram, Proof } from 'o1js'; -import { tic, toc } from '../examples/utils/tic-toc.node.js'; +import { SelfProof, Field, ZkProgram, Proof, JsonProof } from 'o1js'; +import { tic, toc } from '../examples/utils/tic-toc.js'; let MaxProofsVerifiedZero = ZkProgram({ name: 'no-recursion', @@ -100,12 +100,12 @@ async function testRecursion( ) { console.log(`testing maxProofsVerified = ${maxProofsVerified}`); - let ProofClass = ZkProgram.Proof(Program); + class ProofClass extends ZkProgram.Proof(Program) {} tic('executing base case'); - let initialProof = await Program.baseCase(Field(0)); + let { proof: initialProof } = await Program.baseCase(Field(0)); toc(); - initialProof = testJsonRoundtrip(ProofClass, initialProof); + initialProof = await testJsonRoundtrip(ProofClass, initialProof); initialProof.verify(); initialProof.publicInput.assertEquals(Field(0)); @@ -115,13 +115,13 @@ async function testRecursion( ); } - let p1, p2; + let p1: Proof, p2: Proof; if (initialProof.maxProofsVerified === 0) return; tic('executing mergeOne'); - p1 = await Program.mergeOne(Field(1), initialProof); + p1 = (await Program.mergeOne(Field(1), initialProof)).proof; toc(); - p1 = testJsonRoundtrip(ProofClass, p1); + p1 = await testJsonRoundtrip(ProofClass, p1); p1.verify(); p1.publicInput.assertEquals(Field(1)); if (p1.maxProofsVerified != maxProofsVerified) { @@ -132,9 +132,9 @@ async function testRecursion( if (initialProof.maxProofsVerified === 1) return; tic('executing mergeTwo'); - p2 = await Program.mergeTwo(Field(2), initialProof, p1); + p2 = (await Program.mergeTwo(Field(2), initialProof, p1)).proof; toc(); - p2 = testJsonRoundtrip(ProofClass, p2); + p2 = await testJsonRoundtrip(ProofClass, p2); p2.verify(); p2.publicInput.assertEquals(Field(2)); if (p2.maxProofsVerified != maxProofsVerified) { @@ -144,7 +144,10 @@ async function testRecursion( } } -function testJsonRoundtrip(ProofClass: any, proof: Proof) { +function testJsonRoundtrip( + ProofClass: { fromJSON: (p: JsonProof) => Promise> }, + proof: Proof +) { let jsonProof = proof.toJSON(); console.log( 'json roundtrip', From 55f8ce96eb60a48cff8fbe0bfec3829bc354077c Mon Sep 17 00:00:00 2001 From: Gregor Date: Fri, 29 Nov 2024 08:39:55 +0100 Subject: [PATCH 238/328] delete unused and outdated test / script --- run-minimal-mina-tests.sh | 6 --- src/tests/inductive-proofs-small.ts | 81 ----------------------------- 2 files changed, 87 deletions(-) delete mode 100755 run-minimal-mina-tests.sh delete mode 100644 src/tests/inductive-proofs-small.ts diff --git a/run-minimal-mina-tests.sh b/run-minimal-mina-tests.sh deleted file mode 100755 index 327b5adfd3..0000000000 --- a/run-minimal-mina-tests.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash -set -e - -npm run dev - -./run src/tests/inductive-proofs-small.ts --bundle diff --git a/src/tests/inductive-proofs-small.ts b/src/tests/inductive-proofs-small.ts deleted file mode 100644 index f20f7b4fc8..0000000000 --- a/src/tests/inductive-proofs-small.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { SelfProof, Field, ZkProgram, Proof } from 'o1js'; -import { tic, toc } from '../examples/utils/tic-toc.node.js'; - -let MaxProofsVerifiedOne = ZkProgram({ - name: 'recursive-1', - publicInput: Field, - - methods: { - baseCase: { - privateInputs: [], - - async method(publicInput: Field) { - publicInput.assertEquals(Field(0)); - }, - }, - - mergeOne: { - privateInputs: [SelfProof], - - async method( - publicInput: Field, - earlierProof: SelfProof - ) { - earlierProof.verify(); - earlierProof.publicInput.add(1).assertEquals(publicInput); - }, - }, - }, -}); - -tic('compiling program'); -await MaxProofsVerifiedOne.compile(); -toc(); - -await testRecursion(MaxProofsVerifiedOne, 1); - -async function testRecursion( - Program: typeof MaxProofsVerifiedOne, - maxProofsVerified: number -) { - console.log(`testing maxProofsVerified = ${maxProofsVerified}`); - - let ProofClass = ZkProgram.Proof(Program); - - tic('executing base case'); - let initialProof = await Program.baseCase(Field(0)); - toc(); - initialProof = testJsonRoundtrip(ProofClass, initialProof); - initialProof.verify(); - initialProof.publicInput.assertEquals(Field(0)); - - if (initialProof.maxProofsVerified != maxProofsVerified) { - throw Error( - `Expected initialProof to have maxProofsVerified = ${maxProofsVerified} but has ${initialProof.maxProofsVerified}` - ); - } - - let p1; - if (initialProof.maxProofsVerified === 0) return; - - tic('executing mergeOne'); - p1 = await Program.mergeOne(Field(1), initialProof); - toc(); - p1 = testJsonRoundtrip(ProofClass, p1); - p1.verify(); - p1.publicInput.assertEquals(Field(1)); - if (p1.maxProofsVerified != maxProofsVerified) { - throw Error( - `Expected p1 to have maxProofsVerified = ${maxProofsVerified} but has ${p1.maxProofsVerified}` - ); - } -} - -function testJsonRoundtrip(ProofClass: any, proof: Proof) { - let jsonProof = proof.toJSON(); - console.log( - 'json roundtrip', - JSON.stringify({ ...jsonProof, proof: jsonProof.proof.slice(0, 10) + '..' }) - ); - return ProofClass.fromJSON(jsonProof); -} From 6d1711bf70564ef4a4e05d4968f63b59ecf7cb66 Mon Sep 17 00:00:00 2001 From: Gregor Date: Fri, 29 Nov 2024 09:00:07 +0100 Subject: [PATCH 239/328] simplify `TupleToInstances` type to make it disappear --- src/lib/proof-system/zkprogram.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 6e52fe8d24..09a5245880 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -1094,7 +1094,7 @@ type Infer = T extends Subclass type TupleToInstances = { [I in keyof T]: Infer; -} & any[]; +}; type PrivateInput = ProvableType | Subclass; From 551497acc3b59536567bfb90a2df49eb373bf925 Mon Sep 17 00:00:00 2001 From: Gregor Date: Fri, 29 Nov 2024 09:09:46 +0100 Subject: [PATCH 240/328] expose Proof class on zkprogram --- src/lib/proof-system/zkprogram.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 09a5245880..bcd74d2a08 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -250,6 +250,11 @@ function ZkProgram< >; }; + Proof: typeof Proof< + InferProvableOrUndefined>, + InferProvableOrVoid> + >; + proofsEnabled: boolean; setProofsEnabled(proofsEnabled: boolean): void; } & { @@ -549,13 +554,14 @@ function ZkProgram< rawMethods: Object.fromEntries( methodKeys.map((key) => [key, methods[key].method]) ) as any, + proveRecursively, + + Proof: SelfProof, proofsEnabled: doProving, setProofsEnabled(proofsEnabled: boolean) { doProving = proofsEnabled; }, - - proveRecursively, }, provers ); From 35fe9def88883268711a6c23313b485041e3de70 Mon Sep 17 00:00:00 2001 From: Gregor Date: Fri, 29 Nov 2024 09:10:36 +0100 Subject: [PATCH 241/328] simplfy some examples --- src/examples/zkprogram/mututal-recursion.ts | 4 +--- src/examples/zkprogram/program-with-input.ts | 8 +++----- src/lib/mina/actions/offchain-state-rollup.ts | 2 +- src/lib/proof-system/proof-system.unit-test.ts | 2 +- src/lib/provable/test/custom-gates-recursion.unit-test.ts | 2 +- src/tests/fake-proof.ts | 2 +- src/tests/inductive-proofs.ts | 2 +- 7 files changed, 9 insertions(+), 13 deletions(-) diff --git a/src/examples/zkprogram/mututal-recursion.ts b/src/examples/zkprogram/mututal-recursion.ts index 542bae1c2b..89b9d7bed5 100644 --- a/src/examples/zkprogram/mututal-recursion.ts +++ b/src/examples/zkprogram/mututal-recursion.ts @@ -47,15 +47,13 @@ const add = ZkProgram({ }, }); -const AddProof = ZkProgram.Proof(add); - const multiply = ZkProgram({ name: 'multiply', publicInput: Undefined, publicOutput: Field, methods: { performMultiplication: { - privateInputs: [Field, AddProof], + privateInputs: [Field, add.Proof], async method(field: Field, addProof: Proof) { addProof.verify(); const multiplicationResult = addProof.publicOutput.mul(field); diff --git a/src/examples/zkprogram/program-with-input.ts b/src/examples/zkprogram/program-with-input.ts index a6117771b3..3325538c05 100644 --- a/src/examples/zkprogram/program-with-input.ts +++ b/src/examples/zkprogram/program-with-input.ts @@ -35,8 +35,6 @@ MyProgram.publicOutputType satisfies Provable; MyProgram.privateInputTypes; MyProgram.auxiliaryOutputTypes; -let MyProof = ZkProgram.Proof(MyProgram); - console.log('program digest', await MyProgram.digest()); console.log('compiling MyProgram...'); @@ -45,7 +43,7 @@ console.log('verification key', verificationKey.data.slice(0, 10) + '..'); console.log('proving base case...'); let { proof } = await MyProgram.baseCase(Field(0)); -proof = await testJsonRoundtrip(MyProof, proof); +proof = await testJsonRoundtrip(MyProgram.Proof, proof); // type sanity check proof satisfies Proof; @@ -60,7 +58,7 @@ console.log('ok (alternative)?', ok); console.log('proving step 1...'); let { proof: proof1 } = await MyProgram.inductiveCase(Field(1), proof); -proof1 = await testJsonRoundtrip(MyProof, proof1); +proof1 = await testJsonRoundtrip(MyProgram.Proof, proof1); console.log('verify...'); ok = await verify(proof1, verificationKey); @@ -72,7 +70,7 @@ console.log('ok (alternative)?', ok); console.log('proving step 2...'); let { proof: proof2 } = await MyProgram.inductiveCase(Field(2), proof1); -proof2 = await testJsonRoundtrip(MyProof, proof2); +proof2 = await testJsonRoundtrip(MyProgram.Proof, proof2); console.log('verify...'); ok = await verify(proof2.toJSON(), verificationKey); diff --git a/src/lib/mina/actions/offchain-state-rollup.ts b/src/lib/mina/actions/offchain-state-rollup.ts index a6ab88d9b1..18b772f1ac 100644 --- a/src/lib/mina/actions/offchain-state-rollup.ts +++ b/src/lib/mina/actions/offchain-state-rollup.ts @@ -239,7 +239,7 @@ function OffchainStateRollup({ }, }); - let RollupProof = ZkProgram.Proof(offchainStateRollup); + let RollupProof = offchainStateRollup.Proof; let isCompiled = false; diff --git a/src/lib/proof-system/proof-system.unit-test.ts b/src/lib/proof-system/proof-system.unit-test.ts index c6b570f714..da3933c5f5 100644 --- a/src/lib/proof-system/proof-system.unit-test.ts +++ b/src/lib/proof-system/proof-system.unit-test.ts @@ -26,7 +26,7 @@ const EmptyProgram = ZkProgram({ methods: { run: { privateInputs: [], async method(_) {} } }, }); -class EmptyProof extends ZkProgram.Proof(EmptyProgram) {} +class EmptyProof extends EmptyProgram.Proof {} // unit-test zkprogram creation helpers: // -) sortMethodArguments diff --git a/src/lib/provable/test/custom-gates-recursion.unit-test.ts b/src/lib/provable/test/custom-gates-recursion.unit-test.ts index 4d14fecc18..c16d0696ec 100644 --- a/src/lib/provable/test/custom-gates-recursion.unit-test.ts +++ b/src/lib/provable/test/custom-gates-recursion.unit-test.ts @@ -29,7 +29,7 @@ let emptyProgram = ZkProgram({ name: 'empty', methods: { run: { privateInputs: [], async method() {} } }, }); -class EmptyProof extends ZkProgram.Proof(emptyProgram) {} +class EmptyProof extends emptyProgram.Proof {} let program = ZkProgram({ name: 'ecdsa', diff --git a/src/tests/fake-proof.ts b/src/tests/fake-proof.ts index 5cc2338bfb..e29dfb7f71 100644 --- a/src/tests/fake-proof.ts +++ b/src/tests/fake-proof.ts @@ -43,7 +43,7 @@ const FakeProgram = ZkProgram({ }, }); -class RealProof extends ZkProgram.Proof(RealProgram) {} +class RealProof extends RealProgram.Proof {} class Nested extends Struct({ inner: RealProof }) {} const RecursiveProgram = ZkProgram({ diff --git a/src/tests/inductive-proofs.ts b/src/tests/inductive-proofs.ts index 7102eae5c0..349d3a753c 100644 --- a/src/tests/inductive-proofs.ts +++ b/src/tests/inductive-proofs.ts @@ -100,7 +100,7 @@ async function testRecursion( ) { console.log(`testing maxProofsVerified = ${maxProofsVerified}`); - class ProofClass extends ZkProgram.Proof(Program) {} + class ProofClass extends Program.Proof {} tic('executing base case'); let { proof: initialProof } = await Program.baseCase(Field(0)); From 62beb20647be6dca9ca0f32cdf92f703ac1c1a88 Mon Sep 17 00:00:00 2001 From: Gregor Date: Fri, 29 Nov 2024 11:24:00 +0100 Subject: [PATCH 242/328] extract declared proofs during analyze, and refactor how maxProofsVerified is computed --- src/lib/mina/account-update.ts | 2 +- src/lib/mina/zkapp.ts | 29 +++-- .../proof-system/proof-system.unit-test.ts | 3 +- src/lib/proof-system/proof.ts | 4 +- src/lib/proof-system/zkprogram.ts | 102 +++++++++++++----- 5 files changed, 100 insertions(+), 40 deletions(-) diff --git a/src/lib/mina/account-update.ts b/src/lib/mina/account-update.ts index 83ad585372..3daf074aa0 100644 --- a/src/lib/mina/account-update.ts +++ b/src/lib/mina/account-update.ts @@ -2151,7 +2151,7 @@ async function createZkappProof( } ); - let maxProofsVerified = ZkappClass._maxProofsVerified!; + let maxProofsVerified = await ZkappClass.getMaxProofsVerified(); const Proof = ZkappClass.Proof(); return new Proof({ publicInput, diff --git a/src/lib/mina/zkapp.ts b/src/lib/mina/zkapp.ts index 8720f33556..949417b58c 100644 --- a/src/lib/mina/zkapp.ts +++ b/src/lib/mina/zkapp.ts @@ -44,13 +44,14 @@ import { import { analyzeMethod, compileProgram, + computeMaxProofsVerified, Empty, getPreviousProofsForProver, MethodInterface, sortMethodArguments, VerificationKey, } from '../proof-system/zkprogram.js'; -import { Proof } from '../proof-system/proof.js'; +import { Proof, ProofClass } from '../proof-system/proof.js'; import { PublicKey } from '../provable/crypto/signature.js'; import { InternalStateType, @@ -154,11 +155,6 @@ function method( // FIXME: overriding a method implies pushing a separate method entry here, yielding two entries with the same name // this should only be changed once we no longer share the _methods array with the parent class (otherwise a subclass declaration messes up the parent class) ZkappClass._methods.push(methodEntry); - ZkappClass._maxProofsVerified ??= 0; - ZkappClass._maxProofsVerified = Math.max( - ZkappClass._maxProofsVerified, - methodEntry.numberOfProofs - ) as 0 | 1 | 2; let func = descriptor.value as AsyncFunction; descriptor.value = wrapMethod(func, ZkappClass, internalMethodEntry); } @@ -593,10 +589,10 @@ class SmartContract extends SmartContractBase { rows: number; digest: string; gates: Gate[]; + proofs: ProofClass[]; } >; // keyed by method name static _provers?: Pickles.Prover[]; - static _maxProofsVerified?: 0 | 1 | 2; static _verificationKey?: { data: string; hash: Field }; /** @@ -644,6 +640,7 @@ class SmartContract extends SmartContractBase { forceRecompile = false, } = {}) { let methodIntfs = this._methods ?? []; + let methodKeys = methodIntfs.map(({ methodName }) => methodName); let methods = methodIntfs.map(({ methodName }) => { return async ( publicInput: unknown, @@ -657,13 +654,15 @@ class SmartContract extends SmartContractBase { }); // run methods once to get information that we need already at compile time let methodsMeta = await this.analyzeMethods(); - let gates = methodIntfs.map((intf) => methodsMeta[intf.methodName].gates); + let gates = methodKeys.map((k) => methodsMeta[k].gates); + let proofs = methodKeys.map((k) => methodsMeta[k].proofs); let { verificationKey, provers, verify } = await compileProgram({ publicInputType: ZkappPublicInput, publicOutputType: Empty, methodIntfs, methods, gates, + proofs, proofSystemTag: this, cache, forceRecompile, @@ -689,6 +688,17 @@ class SmartContract extends SmartContractBase { return hash.toBigInt().toString(16); } + /** + * The maximum number of proofs that are verified by any of the zkApp methods. + * This is an internal parameter needed by the proof system. + */ + static async getMaxProofsVerified() { + let methodData = await this.analyzeMethods(); + return computeMaxProofsVerified( + Object.values(methodData).map((d) => d.proofs.length) + ); + } + /** * Deploys a {@link SmartContract}. * @@ -1189,7 +1199,7 @@ super.init(); try { for (let methodIntf of methodIntfs) { let accountUpdate: AccountUpdate; - let { rows, digest, gates, summary } = await analyzeMethod( + let { rows, digest, gates, summary, proofs } = await analyzeMethod( ZkappPublicInput, methodIntf, async (publicInput, publicKey, tokenId, ...args) => { @@ -1207,6 +1217,7 @@ super.init(); rows, digest, gates, + proofs, }; if (printSummary) console.log(methodIntf.methodName, summary()); } diff --git a/src/lib/proof-system/proof-system.unit-test.ts b/src/lib/proof-system/proof-system.unit-test.ts index c6b570f714..a88acb8611 100644 --- a/src/lib/proof-system/proof-system.unit-test.ts +++ b/src/lib/proof-system/proof-system.unit-test.ts @@ -54,7 +54,6 @@ it('pickles rule creation', async () => { expect(methodIntf).toEqual({ methodName: 'main', args: [EmptyProof, Bool], - numberOfProofs: 1, }); // store compiled tag @@ -67,6 +66,7 @@ it('pickles rule creation', async () => { main as AnyFunction, { name: 'mock' }, methodIntf, + [], [] ); @@ -146,6 +146,7 @@ it('pickles rule creation: nested proof', async () => { main as AnyFunction, { name: 'mock' }, methodIntf, + [], [] ); diff --git a/src/lib/proof-system/proof.ts b/src/lib/proof-system/proof.ts index 1fc4a230fb..78a5a8d825 100644 --- a/src/lib/proof-system/proof.ts +++ b/src/lib/proof-system/proof.ts @@ -15,13 +15,15 @@ import { ProvableType } from '../provable/types/provable-intf.js'; import { ZkProgramContext } from './zkprogram-context.js'; // public API -export { ProofBase, Proof, DynamicProof }; +export { ProofBase, Proof, DynamicProof, ProofClass }; // internal API export { dummyProof, extractProofs, extractProofTypes, type ProofValue }; type MaxProofs = 0 | 1 | 2; +type ProofClass = Subclass; + class ProofBase { static publicInputType: FlexibleProvablePure = undefined as any; static publicOutputType: FlexibleProvablePure = undefined as any; diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 2cb0222b3b..865d01cb99 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -45,6 +45,7 @@ import { extractProofTypes, Proof, ProofBase, + ProofClass, ProofValue, } from './proof.js'; import { @@ -79,6 +80,7 @@ export { analyzeMethod, Prover, dummyBase64Proof, + computeMaxProofsVerified, }; type Undefined = undefined; @@ -291,7 +293,15 @@ function ZkProgram< ) ); let methodFunctions = methodKeys.map((key) => methods[key].method); - let maxProofsVerified = getMaxProofsVerified(methodIntfs); + let maxProofsVerified: undefined | 0 | 1 | 2 = undefined; + + async function getMaxProofsVerified() { + if (maxProofsVerified !== undefined) return maxProofsVerified; + let methodsMeta = await analyzeMethods(); + let proofs = methodKeys.map((k) => methodsMeta[k].proofs.length); + maxProofsVerified = computeMaxProofsVerified(proofs); + return maxProofsVerified; + } async function analyzeMethods() { let methodsMeta: Record< @@ -314,6 +324,7 @@ function ZkProgram< let compileOutput: | { provers: Pickles.Prover[]; + maxProofsVerified: 0 | 1 | 2; verify: ( statement: Pickles.Statement, proof: Pickles.Proof @@ -333,6 +344,8 @@ function ZkProgram< if (doProving) { let methodsMeta = await analyzeMethods(); let gates = methodKeys.map((k) => methodsMeta[k].gates); + let proofs = methodKeys.map((k) => methodsMeta[k].proofs); + maxProofsVerified = computeMaxProofsVerified(proofs.map((p) => p.length)); let { provers, verify, verificationKey } = await compileProgram({ publicInputType, @@ -340,6 +353,7 @@ function ZkProgram< methodIntfs, methods: methodFunctions, gates, + proofs, proofSystemTag: selfTag, cache, forceRecompile, @@ -347,7 +361,7 @@ function ZkProgram< state: programState, }); - compileOutput = { provers, verify }; + compileOutput = { provers, verify, maxProofsVerified }; return { verificationKey }; } else { return { @@ -379,13 +393,12 @@ function ZkProgram< let proof = await SelfProof.dummy( publicInput, publicOutput, - maxProofsVerified + await getMaxProofsVerified() ); return { proof, auxiliaryOutput }; } - let picklesProver = compileOutput?.provers?.[i]; - if (picklesProver === undefined) { + if (compileOutput === undefined) { throw Error( `Cannot prove execution of program.${String( key @@ -393,6 +406,8 @@ function ZkProgram< `Try calling \`await program.compile()\` first, this will cache provers in the background.\nIf you compiled your zkProgram with proofs disabled (\`proofsEnabled = false\`), you have to compile it with proofs enabled first.` ); } + let picklesProver = compileOutput.provers[i]; + let maxProofsVerified = compileOutput.maxProofsVerified; let publicInputFields = toFieldConsts(publicInputType, publicInput); let previousProofs = MlArray.to(getPreviousProofsForProver(args)); @@ -479,6 +494,13 @@ function ZkProgram< ([arg, type]) => Provable.toConstant(type, arg) ); let { proof } = await prover(constInput, ...(constArgs as any)); + // let publicOutput = proof.publicOutput; + // let publicOutput = ProvableType.synthesize(publicOutputType); + // return SelfProof.dummy( + // constInput, + // publicOutput, + // await getMaxProofsVerified() + // ); return proof; }); @@ -623,7 +645,8 @@ function sortMethodArguments( ); }); - // extract proofs to count them and for sanity checks + // extract input proofs to count them and for sanity checks + // WARNING: this doesn't include internally declared proofs! let proofs = args.flatMap(extractProofTypes); let numberOfProofs = proofs.length; @@ -644,7 +667,7 @@ function sortMethodArguments( `Suggestion: You can merge more than two proofs by merging two at a time in a binary tree.` ); } - return { methodName, args, numberOfProofs, auxiliaryType }; + return { methodName, args, auxiliaryType }; } function isProvable(type: unknown): type is ProvableType { @@ -664,14 +687,15 @@ function isDynamicProof( return typeof type === 'function' && type.prototype instanceof DynamicProof; } +// TODO: remove this and get proofs during proving with the handler function getPreviousProofsForProver(methodArgs: any[]) { + throw Error('todo: cant get previous proofs before proving'); return methodArgs.flatMap(extractProofs).map((proof) => proof.proof); } type MethodInterface = { methodName: string; args: ProvableType[]; - numberOfProofs: number; returnType?: Provable; auxiliaryType?: Provable; }; @@ -685,6 +709,7 @@ async function compileProgram({ methodIntfs, methods, gates, + proofs, proofSystemTag, cache, forceRecompile, @@ -696,6 +721,7 @@ async function compileProgram({ methodIntfs: MethodInterface[]; methods: ((...args: any) => unknown)[]; gates: Gate[][]; + proofs: ProofClass[][]; proofSystemTag: { name: string }; cache: Cache; forceRecompile: boolean; @@ -716,12 +742,13 @@ If you are using a SmartContract, make sure you are using the @method decorator. proofSystemTag, methodEntry, gates[i], + proofs[i], state ) ); - let maxProofs = getMaxProofsVerified(methodIntfs); - overrideWrapDomain ??= maxProofsToWrapDomain[maxProofs]; + let maxProofs = computeMaxProofsVerified(proofs.map((p) => p.length)); + overrideWrapDomain ??= maxProofsToWrapDomain[maxProofs]; let picklesCache: Pickles.Cache = [ 0, function read_(mlHeader) { @@ -803,19 +830,32 @@ If you are using a SmartContract, make sure you are using the @method decorator. }; } -function analyzeMethod( +async function analyzeMethod( publicInputType: ProvablePure, methodIntf: MethodInterface, method: (...args: any) => unknown ) { - return Provable.constraintSystem(() => { - let args = methodIntf.args.map(emptyWitness); - let publicInput = emptyWitness(publicInputType); - // note: returning the method result here makes this handle async methods - if (publicInputType === Undefined || publicInputType === Void) - return method(...args); - return method(publicInput, ...args); - }); + let result: Awaited>; + let proofs: ProofClass[]; + let id = ZkProgramContext.enter(); + try { + result = await Provable.constraintSystem(() => { + let args = methodIntf.args.map(emptyWitness); + args.forEach((value) => + extractProofs(value).forEach((proof) => proof.declare()) + ); + + let publicInput = emptyWitness(publicInputType); + // note: returning the method result here makes this handle async methods + if (publicInputType === Undefined || publicInputType === Void) + return method(...args); + return method(publicInput, ...args); + }); + proofs = ZkProgramContext.getDeclaredProofs().map(({ Proof }) => Proof); + } finally { + ZkProgramContext.leave(id); + } + return { ...result, proofs }; } function inCircuitVkHash(inCircuitVk: unknown): Field { @@ -838,6 +878,7 @@ function picklesRuleFromFunction( proofSystemTag: { name: string }, { methodName, args, auxiliaryType }: MethodInterface, gates: Gate[], + verifiedProofs: ProofClass[], state?: ReturnType ): Pickles.Rule { async function main( @@ -881,7 +922,13 @@ function picklesRuleFromFunction( ZkProgramContext.leave(id); } - // now all proofs are declared - extract their statements for Pickles + // now all proofs are declared - check that we got as many as during compile time + assert( + proofs.length === verifiedProofs.length, + `Expected ${verifiedProofs.length} proofs, but got ${proofs.length}` + ); + + // extract proof statements for Pickles let previousStatements = proofs.map( ({ proof }): Pickles.Statement => { let fields = proof.publicFields(); @@ -953,14 +1000,13 @@ function picklesRuleFromFunction( }; } - let proofs: Subclass[] = args.flatMap(extractProofTypes); - if (proofs.length > 2) { + if (verifiedProofs.length > 2) { throw Error( `${proofSystemTag.name}.${methodName}() has more than two proof arguments, which is not supported.\n` + `Suggestion: You can merge more than two proofs by merging two at a time in a binary tree.` ); } - let proofsToVerify = proofs.map((Proof) => { + let proofsToVerify = verifiedProofs.map((Proof) => { let tag = Proof.tag(); if (tag === proofSystemTag) return { isSelf: true as const }; else if (isDynamicProof(Proof)) { @@ -1001,11 +1047,11 @@ function picklesRuleFromFunction( }; } -function getMaxProofsVerified(methodIntfs: MethodInterface[]) { - return methodIntfs.reduce( - (acc, { numberOfProofs }) => Math.max(acc, numberOfProofs), - 0 - ) as any as 0 | 1 | 2; +function computeMaxProofsVerified(proofs: number[]) { + return proofs.reduce((acc: number, n) => { + assert(n <= 2, 'Too many proofs'); + return Math.max(acc, n); + }, 0) as 0 | 1 | 2; } function fromFieldVars(type: ProvablePure, fields: MlFieldArray) { From 90c73afde08148ee65e628c1e4c5433fb60415ad Mon Sep 17 00:00:00 2001 From: Gregor Date: Fri, 29 Nov 2024 13:42:45 +0100 Subject: [PATCH 243/328] change bindings API to expect proofs returned from js circuit and not directly as arguments to prover --- src/bindings | 2 +- src/snarky.d.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/bindings b/src/bindings index d6509b9fd0..9bedfb289b 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit d6509b9fd082785ef33eefc3c565ab5e9551dacb +Subproject commit 9bedfb289b3a51be0f4445c229d592ff13c989a3 diff --git a/src/snarky.d.ts b/src/snarky.d.ts index 5f46056cf4..c685778a3d 100644 --- a/src/snarky.d.ts +++ b/src/snarky.d.ts @@ -625,6 +625,7 @@ declare namespace Pickles { main: (publicInput: MlArray) => Promise<{ publicOutput: MlArray; previousStatements: MlArray>; + previousProofs: MlArray; shouldVerify: MlArray; }>; /** @@ -652,8 +653,7 @@ declare namespace Pickles { ]; type Prover = ( - publicInput: MlArray, - previousProofs: MlArray + publicInput: MlArray ) => Promise<[_: 0, publicOutput: MlArray, proof: Proof]>; } From cd3f73f595e921935d52c8bd4b15aff2dae6b556 Mon Sep 17 00:00:00 2001 From: Gregor Date: Fri, 29 Nov 2024 13:43:50 +0100 Subject: [PATCH 244/328] adapt to proofs returned from circuit --- src/lib/mina/account-update.ts | 12 ++---------- src/lib/mina/zkapp.ts | 4 ---- src/lib/proof-system/zkprogram.ts | 32 +++++++------------------------ 3 files changed, 9 insertions(+), 39 deletions(-) diff --git a/src/lib/mina/account-update.ts b/src/lib/mina/account-update.ts index 3daf074aa0..1dd76cc222 100644 --- a/src/lib/mina/account-update.ts +++ b/src/lib/mina/account-update.ts @@ -655,7 +655,6 @@ type LazyProof = { kind: 'lazy-proof'; methodName: string; args: any[]; - previousProofs: Pickles.Proof[]; ZkappClass: typeof SmartContract; memoized: { fields: Field[]; aux: any[] }[]; blindingValue: Field; @@ -2116,14 +2115,7 @@ async function addProof( async function createZkappProof( prover: Pickles.Prover, - { - methodName, - args, - previousProofs, - ZkappClass, - memoized, - blindingValue, - }: LazyProof, + { methodName, args, ZkappClass, memoized, blindingValue }: LazyProof, { transaction, accountUpdate, index }: ZkappProverData ): Promise> { let publicInput = accountUpdate.toPublicInput(transaction); @@ -2141,7 +2133,7 @@ async function createZkappProof( blindingValue, }); try { - return await prover(publicInputFields, MlArray.to(previousProofs)); + return await prover(publicInputFields); } catch (err) { console.error(`Error when proving ${ZkappClass.name}.${methodName}()`); throw err; diff --git a/src/lib/mina/zkapp.ts b/src/lib/mina/zkapp.ts index 949417b58c..094b308a34 100644 --- a/src/lib/mina/zkapp.ts +++ b/src/lib/mina/zkapp.ts @@ -46,7 +46,6 @@ import { compileProgram, computeMaxProofsVerified, Empty, - getPreviousProofsForProver, MethodInterface, sortMethodArguments, VerificationKey, @@ -337,8 +336,6 @@ function wrapMethod( { methodName: methodIntf.methodName, args: clonedArgs, - // proofs actually don't have to be cloned - previousProofs: getPreviousProofsForProver(actualArgs), ZkappClass, memoized, blindingValue, @@ -429,7 +426,6 @@ function wrapMethod( { methodName: methodIntf.methodName, args: constantArgs, - previousProofs: getPreviousProofsForProver(constantArgs), ZkappClass, memoized, blindingValue: constantBlindingValue, diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 865d01cb99..9f5de9b30d 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -73,7 +73,6 @@ export { export { CompiledTag, sortMethodArguments, - getPreviousProofsForProver, MethodInterface, picklesRuleFromFunction, compileProgram, @@ -384,11 +383,10 @@ function ZkProgram< ): RegularProver { return async function prove_(publicInput, ...args) { if (!doProving) { - let previousProofs = MlArray.to(getPreviousProofsForProver(args)); - let { publicOutput, auxiliaryOutput } = - (await (methods[key].method as any)(publicInput, previousProofs)) ?? - {}; + (hasPublicInput + ? await (methods[key].method as any)(publicInput, ...args) + : await (methods[key].method as any)(...args)) ?? {}; let proof = await SelfProof.dummy( publicInput, @@ -409,12 +407,11 @@ function ZkProgram< let picklesProver = compileOutput.provers[i]; let maxProofsVerified = compileOutput.maxProofsVerified; let publicInputFields = toFieldConsts(publicInputType, publicInput); - let previousProofs = MlArray.to(getPreviousProofsForProver(args)); let id = snarkContext.enter({ witnesses: args, inProver: true }); let result: UnwrapPromise>; try { - result = await picklesProver(publicInputFields, previousProofs); + result = await picklesProver(publicInputFields); } finally { snarkContext.leave(id); } @@ -494,13 +491,6 @@ function ZkProgram< ([arg, type]) => Provable.toConstant(type, arg) ); let { proof } = await prover(constInput, ...(constArgs as any)); - // let publicOutput = proof.publicOutput; - // let publicOutput = ProvableType.synthesize(publicOutputType); - // return SelfProof.dummy( - // constInput, - // publicOutput, - // await getMaxProofsVerified() - // ); return proof; }); @@ -687,12 +677,6 @@ function isDynamicProof( return typeof type === 'function' && type.prototype instanceof DynamicProof; } -// TODO: remove this and get proofs during proving with the handler -function getPreviousProofsForProver(methodArgs: any[]) { - throw Error('todo: cant get previous proofs before proving'); - return methodArgs.flatMap(extractProofs).map((proof) => proof.proof); -} - type MethodInterface = { methodName: string; args: ProvableType[]; @@ -804,12 +788,9 @@ If you are using a SmartContract, make sure you are using the @method decorator. // wrap provers let wrappedProvers = provers.map( (prover): Pickles.Prover => - async function picklesProver( - publicInput: MlFieldConstArray, - previousProofs: MlArray - ) { + async function picklesProver(publicInput: MlFieldConstArray) { return prettifyStacktracePromise( - withThreadPool(() => prover(publicInput, previousProofs)) + withThreadPool(() => prover(publicInput)) ); } ); @@ -994,6 +975,7 @@ function picklesRuleFromFunction( return { publicOutput: MlFieldArray.to(publicOutput), previousStatements: MlArray.to(previousStatements), + previousProofs: MlArray.to(proofs.map(({ proof }) => proof.proof)), shouldVerify: MlArray.to( proofs.map((proof) => proof.proof.shouldVerify.toField().value) ), From 5df3ca256567c1027386a9846feb3276763e9256 Mon Sep 17 00:00:00 2001 From: Gregor Date: Fri, 29 Nov 2024 13:44:30 +0100 Subject: [PATCH 245/328] extend internal proving test --- src/tests/inductive-proofs-internal.ts | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/tests/inductive-proofs-internal.ts b/src/tests/inductive-proofs-internal.ts index 7d528fe805..c2aefbf36d 100644 --- a/src/tests/inductive-proofs-internal.ts +++ b/src/tests/inductive-proofs-internal.ts @@ -1,4 +1,4 @@ -import { Field, ZkProgram, assert, Provable } from 'o1js'; +import { Field, ZkProgram, assert, Provable, Proof } from 'o1js'; import { tic, toc } from '../examples/utils/tic-toc.js'; let log: string[] = []; @@ -49,8 +49,26 @@ let MaxProofsVerifiedTwo = ZkProgram({ }, }, }); + +let Wrapper = ZkProgram({ + name: 'wraps-recursive-2', + + methods: { + wrap: { + privateInputs: [ZkProgram.Proof(MaxProofsVerifiedTwo)], + + async method(proof: Proof) { + proof.verify(); + let x = proof.publicOutput; + x.assertLessThan(30); + }, + }, + }, +}); + tic('compiling'); await MaxProofsVerifiedTwo.compile(); +await Wrapper.compile(); toc(); tic('executing 4 proofs'); @@ -66,3 +84,8 @@ assert(log[0] === 'mergeTwo', 'log[0] === "mergeTwo"'); assert(log[1] === 'baseCase', 'log[1] === "baseCase"'); assert(log[2] === 'mergeOne', 'log[2] === "mergeOne"'); assert(log[3] === 'baseCase', 'log[3] === "baseCase"'); + +tic('execute wrapper proof'); +let { proof: wrapperProof } = await Wrapper.wrap(proof); +toc(); +assert(await Wrapper.verify(wrapperProof), 'Wrapper proof is not valid'); From e4143c5186732d1505a881a31bdae3f45d44d866 Mon Sep 17 00:00:00 2001 From: Gregor Date: Fri, 29 Nov 2024 14:01:18 +0100 Subject: [PATCH 246/328] add adversarial test --- src/tests/fake-proof.ts | 45 ++++++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/src/tests/fake-proof.ts b/src/tests/fake-proof.ts index 5cc2338bfb..55f0433b79 100644 --- a/src/tests/fake-proof.ts +++ b/src/tests/fake-proof.ts @@ -9,11 +9,11 @@ import { Struct, Field, Proof, + Unconstrained, + Provable, } from 'o1js'; import assert from 'assert'; -let callRecursive = () => {}; - const RealProgram = ZkProgram({ name: 'real', publicOutput: UInt64, @@ -21,7 +21,6 @@ const RealProgram = ZkProgram({ make: { privateInputs: [UInt64], async method(value: UInt64) { - callRecursive(); let expected = UInt64.from(34); value.assertEquals(expected); return { publicOutput: value.add(1) }; @@ -63,10 +62,21 @@ const RecursiveProgram = ZkProgram({ }, }, verifyInternal: { - privateInputs: [], - async method() { - let x = await RealProgram.proveRecursively.make(UInt64.from(34)); - x.assertEquals(UInt64.from(35)); + privateInputs: [Unconstrained | undefined>], + async method( + fakeProof: Unconstrained | undefined> + ) { + // witness either fake proof from input, or real proof + let proof = await Provable.witnessAsync(RealProof, async () => { + let maybeFakeProof = fakeProof.get(); + if (maybeFakeProof !== undefined) return maybeFakeProof; + + let { proof } = await RealProgram.make(UInt64.from(34)); + return proof; + }); + + proof.declare(); + proof.verify(); }, }, }, @@ -133,11 +143,10 @@ for (let proof of [fakeProof, dummyProof]) { }, 'recursive program rejects fake proof (nested)'); } +// zkprogram accepts proof (nested) const { proof: recursiveProofNested } = await RecursiveProgram.verifyNested( Field(0), - { - inner: realProof, - } + { inner: realProof } ); assert( await verify(recursiveProofNested, programVk), @@ -146,14 +155,22 @@ assert( console.log('fake proof test passed for nested proofs 🎉'); -// test internal proof +// same test for internal proofs -callRecursive = () => console.log('creating a proof inside another!!!'); +for (let proof of [fakeProof, dummyProof]) { + // zkprogram rejects proof (internal) + await assert.rejects(async () => { + await RecursiveProgram.verifyInternal(Unconstrained.from(proof)); + }, 'recursive program rejects fake proof (internal)'); +} -const { proof: internalProof } = await RecursiveProgram.verifyInternal(); +// zkprogram accepts proof (internal) +const { proof: internalProof } = await RecursiveProgram.verifyInternal( + Unconstrained.from(undefined) +); assert( await verify(internalProof, programVk), 'recursive program accepts internal proof' ); -console.log('positive test passed for internal proofs 🎉'); +console.log('fake proof test passed for internal proofs 🎉'); From 34208dfb7e958517a2781c72efa1020206e9734e Mon Sep 17 00:00:00 2001 From: Gregor Date: Fri, 29 Nov 2024 14:35:22 +0100 Subject: [PATCH 247/328] bindings --- src/bindings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bindings b/src/bindings index 9bedfb289b..e10fab968d 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit 9bedfb289b3a51be0f4445c229d592ff13c989a3 +Subproject commit e10fab968db96ef25554c5ac81afac52e40d680c From 1a410b1ea8cc4ab0261db1106eb857cb1ada52d2 Mon Sep 17 00:00:00 2001 From: Gregor Date: Fri, 29 Nov 2024 14:48:05 +0100 Subject: [PATCH 248/328] fix unit test --- src/lib/proof-system/proof-system.unit-test.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/lib/proof-system/proof-system.unit-test.ts b/src/lib/proof-system/proof-system.unit-test.ts index a88acb8611..67dfca967f 100644 --- a/src/lib/proof-system/proof-system.unit-test.ts +++ b/src/lib/proof-system/proof-system.unit-test.ts @@ -67,7 +67,7 @@ it('pickles rule creation', async () => { { name: 'mock' }, methodIntf, [], - [] + [EmptyProof] ); await equivalentAsync( @@ -133,7 +133,6 @@ it('pickles rule creation: nested proof', async () => { expect(methodIntf).toEqual({ methodName: 'main', args: [NestedProof2], - numberOfProofs: 2, }); // store compiled tag @@ -147,7 +146,7 @@ it('pickles rule creation: nested proof', async () => { { name: 'mock' }, methodIntf, [], - [] + [EmptyProof, EmptyProof] ); let dummy = await EmptyProof.dummy(Field(0), undefined, 0); From db8a120a0595a156ae3a5fc1034b63c14aa40a2d Mon Sep 17 00:00:00 2001 From: Gregor Date: Fri, 29 Nov 2024 15:37:31 +0100 Subject: [PATCH 249/328] fixup --- src/lib/proof-system/zkprogram.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index e96e2b08de..9f11721cf3 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -542,9 +542,7 @@ function ZkProgram< const program = Object.assign( selfTag, { - async maxProofsVerified() { - return maxProofsVerified; - }, + maxProofsVerified: getMaxProofsVerified, compile, verify, From d383fe0504c70d5eb81ea89bd7914193a9538c38 Mon Sep 17 00:00:00 2001 From: Gregor Date: Fri, 29 Nov 2024 15:46:58 +0100 Subject: [PATCH 250/328] fixup --- src/lib/proof-system/zkprogram.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 31d8f42cfe..c39d39e552 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -502,6 +502,7 @@ function ZkProgram< let cond = condition.toBoolean(); if (!cond) { let publicOutput = ProvableType.synthesize(publicOutputType); + let maxProofsVerified = compileOutput?.maxProofsVerified!; return SelfProof.dummy( publicInput, publicOutput, From 63aeb5063075a65ceacb7deedba191280282f723 Mon Sep 17 00:00:00 2001 From: ymekuria Date: Mon, 2 Dec 2024 00:23:14 +0900 Subject: [PATCH 251/328] feat(zkprogram.ts): remove nonPureOutputExists conditional check --- src/lib/proof-system/zkprogram.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 92ebf9f872..29cd5d663d 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -874,11 +874,7 @@ function picklesRuleFromFunction( if (result?.publicOutput) { // store the nonPure auxiliary data in program state cache if it exists let nonPureOutput = publicOutputType.toAuxiliary(result.publicOutput); - let nonPureOutputExists = nonPureOutput.length !== 0; - - if (state !== undefined && nonPureOutputExists) { - state.setNonPureOutput(nonPureOutput); - } + state?.setNonPureOutput(nonPureOutput); } proofs.forEach(({ Proof, proof }) => { From 2603799cba9f19fac8adb7cd6c2fd696f901c935 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ana=C3=AFs=20Querol?= Date: Mon, 2 Dec 2024 12:17:26 +0100 Subject: [PATCH 252/328] impossibilitating -> breaking Co-authored-by: Coby --- README-nix.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README-nix.md b/README-nix.md index 2defa96754..463edf26b4 100644 --- a/README-nix.md +++ b/README-nix.md @@ -257,7 +257,7 @@ to install it from scratch. When several clones of the repository are present in the system and both have used Nix (or if it has been moved from one location to another), Nix might cache -an old path, impossibilitating builds. For example, typing `nix develop mina` +an old path, breaking builds. For example, typing `nix develop mina` would complain and produce the following error: ```console From 927d115a8d0084d17c8f040da376abb69e714a93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ana=C3=AFs=20Querol?= Date: Mon, 2 Dec 2024 12:17:40 +0100 Subject: [PATCH 253/328] adviceable -> advisable Co-authored-by: Coby --- README-nix.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README-nix.md b/README-nix.md index 463edf26b4..e0849e2ec1 100644 --- a/README-nix.md +++ b/README-nix.md @@ -250,7 +250,7 @@ error: "/nix/store/w30zw23kmgks77d870i502a3185hjycv-rust/lib/rustlib/src/rust/Ca #### Fix Install `cargo` on your host machine. If doing so does not solve the problem, it -is very likely that the whole Nix setup has gone wrong and it is very adviceable +is very likely that the whole Nix setup has gone wrong and it is very advisable to install it from scratch. ### Old path From 2555cce17f950b4c0f51d39f7fe8095289d077f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ana=C3=AFs=20Querol?= Date: Mon, 2 Dec 2024 12:18:20 +0100 Subject: [PATCH 254/328] specially -> especially Co-authored-by: Coby --- README-nix.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README-nix.md b/README-nix.md index e0849e2ec1..21d1b3c995 100644 --- a/README-nix.md +++ b/README-nix.md @@ -10,7 +10,7 @@ handle the dependencies required across the codebase, including npm scripts. > **When should I use Nix?** > If you cannot build the codebase locally (due to untrusty package manager, > faulty versioning, or unavailable libraries), it is a good idea to try the Nix -> build instead. This can specially happen if you're using a Mac–and even more +> build instead. This can happen especially if you're using a Mac–and even more > likely–with non-Intel chips. ## Installing Nix From 99549d466cce02056e5b13f576adfd849d376430 Mon Sep 17 00:00:00 2001 From: Coby Date: Mon, 2 Dec 2024 10:43:22 -0500 Subject: [PATCH 255/328] rm tag deletion step --- .github/workflows/release.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 67e89f95bb..707b5245a5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -58,13 +58,6 @@ jobs: git add CHANGELOG.md git commit -m "Update CHANGELOG for new version $NEW_VERSION" - - name: Delete existing release tag - run: | - if git rev-parse $NEW_VERSION >/dev/null 2>&1; then - git tag -d $NEW_VERSION - git push origin :refs/tags/$NEW_VERSION - fi - - name: Delete existing release branch run: | if git ls-remote --heads origin release/${NEW_VERSION} | grep release/${NEW_VERSION}; then From 98a60946fb6ebc9e5c0ff9279f1af2483eddb86a Mon Sep 17 00:00:00 2001 From: Geometer1729 <16kuhnb@gmail.com> Date: Mon, 2 Dec 2024 17:42:37 -0500 Subject: [PATCH 256/328] fixes in bindings derivation --- flake.nix | 36 +++++++++++++++++++++++++++++++++--- src/bindings | 2 +- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/flake.nix b/flake.nix index 40ccdfe2ea..cce269049a 100644 --- a/flake.nix +++ b/flake.nix @@ -211,7 +211,30 @@ inherit dune-description; o1js-bindings = pkgs.stdenv.mkDerivation { name = "o1js_bindings"; - src = ./.; + src = with pkgs.lib.fileset; + (toSource { + root = ./.; + fileset = unions [ + ./src/mina + ./src/bindings/scripts + ./src/bindings/js + ./src/bindings/crypto + ./src/bindings/lib + ./src/bindings/mina-transaction/gen/dune + (fileFilter (file: file.hasExt "js") ./src/bindings/mina-transaction) + ./src/bindings/ocaml/lib + ./src/bindings/ocaml/dune + ./src/bindings/ocaml/dune-project + (fileFilter (file: file.hasExt "ml") ./src/bindings/ocaml) + ./package.json + ./package-lock.json + ./src/bindings/ocaml/jsoo_exports + ./dune-project + ./.prettierrc.cjs + ./src/build + ./src/snarky.d.ts + ]; + }); inherit (inputs.mina.devShells."${system}".default) PLONK_WASM_NODEJS PLONK_WASM_WEB @@ -224,6 +247,7 @@ EXPORT_TEST_VECTORS = "${test-vectors}/bin/export_test_vectors"; buildInputs = bindings-pkgs ++ [ pkgs.bash ]; SKIP_MINA_COMMIT = true; + JUST_BINDINGS = true; patchPhase = '' patchShebangs ./src/bindings/scripts/ patchShebangs ./src/bindings/crypto/test-vectors/ @@ -235,11 +259,17 @@ rustup toolchain link nix ${rust-channel} cp -r ${o1js-npm-deps}/lib/node_modules/ . + mkdir -p src/bindings/compiled/node_bindings + echo '// this file exists to prevent TS from type-checking `o1js_node.bc.cjs`' \ + > src/bindings/compiled/node_bindings/o1js_node.bc.d.cts + npm run build:update-bindings - mkdir $out + + mkdir -p $out/mina-transaction pushd ./src/bindings rm -rf ./compiled/_node_bindings - cp -Lr ./compiled ./mina-transaction ./ocaml $out + cp -Lr ./compiled $out + cp -Lr ./mina-transaction/gen $out/mina-transaction/ popd ''; }; diff --git a/src/bindings b/src/bindings index 69299e08de..74936c9693 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit 69299e08deefe3bd2381bfe5d9eafa183e904a15 +Subproject commit 74936c9693549153b8ec16b3f72907cf148311a0 From 6a305a3511da30a854a2b8e3348dbf44ab424607 Mon Sep 17 00:00:00 2001 From: Geometer1729 <16kuhnb@gmail.com> Date: Mon, 2 Dec 2024 20:21:26 -0500 Subject: [PATCH 257/328] add check that the bindings are the same --- .github/workflows/build-bindings.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build-bindings.yml b/.github/workflows/build-bindings.yml index 63c360c27a..75002fb8e6 100644 --- a/.github/workflows/build-bindings.yml +++ b/.github/workflows/build-bindings.yml @@ -28,6 +28,8 @@ jobs: set -Eeu ./pin.sh nix run o1js#update-bindings + #fail if this changes any files + git -C src/bindings diff-index --exit-code HEAD - name: Cleanup the Nix store run: | nix-env --delete-generations old From 31c931bf878a56f6cdfef2663bd877bdf80e2854 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ana=C3=AFs=20Querol?= Date: Tue, 3 Dec 2024 13:47:04 +0100 Subject: [PATCH 258/328] add missing space Co-authored-by: Danny Willems --- README-nix.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README-nix.md b/README-nix.md index 21d1b3c995..f47241f6dc 100644 --- a/README-nix.md +++ b/README-nix.md @@ -1,7 +1,7 @@ # o1js README-nix [Nix](https://nixos.org/) is a tool for package management and system -configurationthat can help developers build a project in a reproducible and +configuration that can help developers build a project in a reproducible and reliable manner, without messing up versions during upgrades. Much like the `mina` repository, you can use Nix to From d269cea2293a401935a26076a1ba451b1a537191 Mon Sep 17 00:00:00 2001 From: Geometer1729 <16kuhnb@gmail.com> Date: Mon, 2 Dec 2024 22:23:07 -0500 Subject: [PATCH 259/328] better error message when bindings differ --- .github/workflows/build-bindings.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-bindings.yml b/.github/workflows/build-bindings.yml index 75002fb8e6..66999dd933 100644 --- a/.github/workflows/build-bindings.yml +++ b/.github/workflows/build-bindings.yml @@ -29,7 +29,8 @@ jobs: ./pin.sh nix run o1js#update-bindings #fail if this changes any files - git -C src/bindings diff-index --exit-code HEAD + cd src/bindings + git diff-index --exit-code HEAD || (git submodule foreach git diff && exit 1) - name: Cleanup the Nix store run: | nix-env --delete-generations old From d68b785fe7b240311b459c823c98f1aa9d2646a2 Mon Sep 17 00:00:00 2001 From: hattyhattington17 <181872047+hattyhattington17@users.noreply.github.com> Date: Tue, 3 Dec 2024 10:04:12 -0700 Subject: [PATCH 260/328] add devnet to networkId type, update mina defaults to use devnet instead of testnet in instance and localblockchain --- src/lib/mina/local-blockchain.ts | 2 +- src/lib/mina/mina-instance.ts | 2 +- src/lib/mina/mina.ts | 2 +- src/mina-signer/src/types.ts | 4 +++- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/lib/mina/local-blockchain.ts b/src/lib/mina/local-blockchain.ts index 2a80874c32..4d049cac09 100644 --- a/src/lib/mina/local-blockchain.ts +++ b/src/lib/mina/local-blockchain.ts @@ -106,7 +106,7 @@ async function LocalBlockchain({ const originalProofsEnabled = proofsEnabled; return { - getNetworkId: () => 'testnet' as NetworkId, + getNetworkId: () => 'devnet' as NetworkId, proofsEnabled, getNetworkConstants() { return { diff --git a/src/lib/mina/mina-instance.ts b/src/lib/mina/mina-instance.ts index 77bc328ba9..640953936b 100644 --- a/src/lib/mina/mina-instance.ts +++ b/src/lib/mina/mina-instance.ts @@ -117,7 +117,7 @@ let activeInstance: Mina = { fetchActions: noActiveInstance, getActions: noActiveInstance, proofsEnabled: true, - getNetworkId: () => 'testnet', + getNetworkId: () => 'devnet', }; /** diff --git a/src/lib/mina/mina.ts b/src/lib/mina/mina.ts index 67edd659e5..c7ea264848 100644 --- a/src/lib/mina/mina.ts +++ b/src/lib/mina/mina.ts @@ -117,7 +117,7 @@ function Network( } | string ): Mina { - let minaNetworkId: NetworkId = 'testnet'; + let minaNetworkId: NetworkId = 'devnet'; let minaGraphqlEndpoint: string; let archiveEndpoint: string; let lightnetAccountManagerEndpoint: string; diff --git a/src/mina-signer/src/types.ts b/src/mina-signer/src/types.ts index 6eb7e75c80..f3692cf03a 100644 --- a/src/mina-signer/src/types.ts +++ b/src/mina-signer/src/types.ts @@ -9,7 +9,9 @@ export type Field = number | bigint | string; export type PublicKey = string; export type PrivateKey = string; export type Signature = SignatureJson; -export type NetworkId = 'mainnet' | 'testnet' | { custom: string }; + +// testnet is deprecated in favor of devnet +export type NetworkId = 'mainnet' | 'devnet' | 'testnet' | { custom: string }; export const NetworkId = { toString(network: NetworkId) { From 8efce38e6c5b56950240c799fd5f028bba44055c Mon Sep 17 00:00:00 2001 From: Geometer1729 <16kuhnb@gmail.com> Date: Tue, 3 Dec 2024 13:18:02 -0500 Subject: [PATCH 261/328] try setting max-jobs --- .github/workflows/build-bindings.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-bindings.yml b/.github/workflows/build-bindings.yml index 66999dd933..655909214a 100644 --- a/.github/workflows/build-bindings.yml +++ b/.github/workflows/build-bindings.yml @@ -27,7 +27,7 @@ jobs: run: | set -Eeu ./pin.sh - nix run o1js#update-bindings + nix run o1js#update-bindings --max-jobs 4 #fail if this changes any files cd src/bindings git diff-index --exit-code HEAD || (git submodule foreach git diff && exit 1) From 4a735cf42be01e4f5d46ce4f527a6a5d1c40be81 Mon Sep 17 00:00:00 2001 From: Geometer1729 <16kuhnb@gmail.com> Date: Tue, 3 Dec 2024 16:14:46 -0500 Subject: [PATCH 262/328] fix diff check I think --- .github/workflows/build-bindings.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-bindings.yml b/.github/workflows/build-bindings.yml index 655909214a..73d2661566 100644 --- a/.github/workflows/build-bindings.yml +++ b/.github/workflows/build-bindings.yml @@ -30,7 +30,7 @@ jobs: nix run o1js#update-bindings --max-jobs 4 #fail if this changes any files cd src/bindings - git diff-index --exit-code HEAD || (git submodule foreach git diff && exit 1) + git diff --exit-code - name: Cleanup the Nix store run: | nix-env --delete-generations old From f0f2440ec2e9145e45325ad08ac536f0fee54bc4 Mon Sep 17 00:00:00 2001 From: Geometer1729 <16kuhnb@gmail.com> Date: Tue, 3 Dec 2024 16:34:33 -0500 Subject: [PATCH 263/328] update mina without rebuilding bindings --- src/bindings | 2 +- src/mina | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bindings b/src/bindings index 74936c9693..fec4c019ef 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit 74936c9693549153b8ec16b3f72907cf148311a0 +Subproject commit fec4c019ef178e570482e72ee8b1a5530b81c3ff diff --git a/src/mina b/src/mina index 6899054b74..f820d28f01 160000 --- a/src/mina +++ b/src/mina @@ -1 +1 @@ -Subproject commit 6899054b745c1323b9d5bcaa62c00bed2ad1ead3 +Subproject commit f820d28f011f709af564aec5d93db07c761a948c From 526881d9ee734d076ebbcf58cc078eb438a38cbf Mon Sep 17 00:00:00 2001 From: hattyhattington17 <181872047+hattyhattington17@users.noreply.github.com> Date: Tue, 3 Dec 2024 11:33:42 -0700 Subject: [PATCH 264/328] update signatures to treat devnet and testnet as identical --- src/lib/mina/token/forest-iterator.unit-test.ts | 3 ++- src/lib/provable/crypto/signature.ts | 10 +++++----- src/mina-signer/src/signature.ts | 9 ++++++--- src/mina-signer/src/signature.unit-test.ts | 17 +++++++++++------ 4 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/lib/mina/token/forest-iterator.unit-test.ts b/src/lib/mina/token/forest-iterator.unit-test.ts index 97f0409ca3..18c6966743 100644 --- a/src/lib/mina/token/forest-iterator.unit-test.ts +++ b/src/lib/mina/token/forest-iterator.unit-test.ts @@ -16,6 +16,7 @@ import { import assert from 'assert'; import { Field, Bool } from '../../provable/wrapped.js'; import { PublicKey } from '../../provable/crypto/signature.js'; +import { NetworkId } from '../../../mina-signer/index.js'; // RANDOM NUMBER GENERATORS for account updates @@ -56,7 +57,7 @@ test.custom({ timeBudget: 1000 })( (flatUpdatesBigint) => { // reference: bigint callforest hash from mina-signer let forestBigint = accountUpdatesToCallForest(flatUpdatesBigint); - let expectedHash = callForestHash(forestBigint, 'testnet'); + let expectedHash = callForestHash(forestBigint, 'devnet'); let flatUpdates = flatUpdatesBigint.map(accountUpdateFromBigint); let forest = AccountUpdateForest.fromFlatArray(flatUpdates); diff --git a/src/lib/provable/crypto/signature.ts b/src/lib/provable/crypto/signature.ts index d1f0cced8a..d5ed209d81 100644 --- a/src/lib/provable/crypto/signature.ts +++ b/src/lib/provable/crypto/signature.ts @@ -266,7 +266,7 @@ class Signature extends CircuitValue { let publicKey = PublicKey.fromPrivateKey(privKey).toGroup(); let d = privKey.s; - // we chose an arbitrary prefix for the signature, and it happened to be 'testnet' + // we chose an arbitrary prefix for the signature // there's no consequences in practice and the signatures can be used with any network // if there needs to be a custom nonce, include it in the message itself let kPrime = Scalar.from( @@ -274,14 +274,14 @@ class Signature extends CircuitValue { { fields: msg.map((f) => f.toBigInt()) }, { x: publicKey.x.toBigInt(), y: publicKey.y.toBigInt() }, d.toBigInt(), - 'testnet' + 'devnet' ) ); let { x: r, y: ry } = Group.generator.scale(kPrime); let k = ry.isOdd().toBoolean() ? kPrime.neg() : kPrime; let h = hashWithPrefix( - signaturePrefix('testnet'), + signaturePrefix('devnet'), msg.concat([publicKey.x, publicKey.y, r]) ); let e = Scalar.fromField(h); @@ -296,11 +296,11 @@ class Signature extends CircuitValue { verify(publicKey: PublicKey, msg: Field[]): Bool { let point = publicKey.toGroup(); - // we chose an arbitrary prefix for the signature, and it happened to be 'testnet' + // we chose an arbitrary prefix for the signature // there's no consequences in practice and the signatures can be used with any network // if there needs to be a custom nonce, include it in the message itself let h = hashWithPrefix( - signaturePrefix('testnet'), + signaturePrefix('devnet'), msg.concat([point.x, point.y, this.r]) ); diff --git a/src/mina-signer/src/signature.ts b/src/mina-signer/src/signature.ts index bd3d384978..64df48d994 100644 --- a/src/mina-signer/src/signature.ts +++ b/src/mina-signer/src/signature.ts @@ -44,7 +44,7 @@ export { }; const networkIdMainnet = 0x01n; -const networkIdTestnet = 0x00n; +const networkIdDevnet = 0x00n; type Signature = { r: Field; s: Scalar }; type SignatureJson = { field: string; scalar: string }; @@ -111,7 +111,7 @@ function verifyFieldElement( * @param privateKey The `privateKey` represents an element of the Pallas scalar field, and should be given as a native bigint. * It can be converted from the base58 string representation using {@link PrivateKey.fromBase58}. * - * @param networkId The `networkId` is either "testnet" or "mainnet" and ensures that testnet transactions can + * @param networkId The `networkId` is either "devnet"/"testnet" or "mainnet" and ensures that testnet transactions can * never be used as valid mainnet transactions. * * @see {@link deriveNonce} and {@link hashMessage} for details on how the nonce and hash are computed. @@ -331,8 +331,9 @@ function getNetworkIdHashInput(network: NetworkId): [bigint, number] { switch (s) { case 'mainnet': return [networkIdMainnet, 8]; + case 'devnet': case 'testnet': - return [networkIdTestnet, 8]; + return [networkIdDevnet, 8]; default: return networkIdOfString(s); } @@ -356,6 +357,7 @@ const signaturePrefix = (network: NetworkId) => { switch (s) { case 'mainnet': return prefixes.signatureMainnet; + case 'devnet': case 'testnet': return prefixes.signatureTestnet; default: @@ -368,6 +370,7 @@ const zkAppBodyPrefix = (network: NetworkId) => { switch (s) { case 'mainnet': return prefixes.zkappBodyMainnet; + case 'devnet': case 'testnet': return prefixes.zkappBodyTestnet; default: diff --git a/src/mina-signer/src/signature.unit-test.ts b/src/mina-signer/src/signature.unit-test.ts index 0565a1b9af..64dc027cf1 100644 --- a/src/mina-signer/src/signature.unit-test.ts +++ b/src/mina-signer/src/signature.unit-test.ts @@ -56,16 +56,21 @@ function checkConsistentSingle( // check that various multi-field hash inputs can be verified function checkCanVerify(msg: HashInput, key: PrivateKey, pk: PublicKey) { + let sigDev = sign(msg, key, 'devnet'); let sigTest = sign(msg, key, 'testnet'); let sigMain = sign(msg, key, 'mainnet'); // verify - let okTestnetTestnet = verify(sigTest, msg, pk, 'testnet'); - let okMainnetTestnet = verify(sigMain, msg, pk, 'testnet'); - let okTestnetMainnet = verify(sigTest, msg, pk, 'mainnet'); + let okTestnetDevnet = verify(sigTest, msg, pk, 'devnet'); + let okDevnetTestnet = verify(sigDev, msg, pk, 'testnet'); + let okDevnetDevnet = verify(sigDev, msg, pk, 'devnet'); + let okMainnetDevnet = verify(sigMain, msg, pk, 'devnet'); + let okDevnetMainnet = verify(sigDev, msg, pk, 'mainnet'); let okMainnetMainnet = verify(sigMain, msg, pk, 'mainnet'); - expect(okTestnetTestnet).toEqual(true); - expect(okMainnetTestnet).toEqual(false); - expect(okTestnetMainnet).toEqual(false); + expect(okTestnetDevnet).toEqual(true); + expect(okDevnetTestnet).toEqual(true); + expect(okDevnetDevnet).toEqual(true); + expect(okMainnetDevnet).toEqual(false); + expect(okDevnetMainnet).toEqual(false); expect(okMainnetMainnet).toEqual(true); } From 28ea4f9a55a3e9cab12a209ca40973f03c81f0a7 Mon Sep 17 00:00:00 2001 From: hattyhattington17 <181872047+hattyhattington17@users.noreply.github.com> Date: Tue, 3 Dec 2024 15:59:01 -0700 Subject: [PATCH 265/328] replace hardcoded instances of testnet with devnet in signing code, constants being generated for the signatures are unchanged --- src/mina-signer/mina-signer.ts | 4 +- src/mina-signer/src/random-transaction.ts | 2 +- src/mina-signer/src/sign-legacy.unit-test.ts | 12 +++- .../src/sign-zkapp-command.unit-test.ts | 16 ++++++ src/mina-signer/src/signature.unit-test.ts | 8 +++ .../src/test-vectors/legacySignatures.ts | 56 +++++++++++++++++++ 6 files changed, 94 insertions(+), 4 deletions(-) diff --git a/src/mina-signer/mina-signer.ts b/src/mina-signer/mina-signer.ts index d6b9793a43..29d53757e0 100644 --- a/src/mina-signer/mina-signer.ts +++ b/src/mina-signer/mina-signer.ts @@ -152,7 +152,7 @@ class Client { */ signFields(fields: bigint[], privateKey: Json.PrivateKey): Signed { let privateKey_ = PrivateKey.fromBase58(privateKey); - let signature = sign({ fields }, privateKey_, 'testnet'); + let signature = sign({ fields }, privateKey_, 'devnet'); return { signature: Signature.toBase58(signature), publicKey: PublicKey.toBase58(PrivateKey.toPublicKey(privateKey_)), @@ -172,7 +172,7 @@ class Client { Signature.fromBase58(signature), { fields: data }, PublicKey.fromBase58(publicKey), - 'testnet' + 'devnet' ); } diff --git a/src/mina-signer/src/random-transaction.ts b/src/mina-signer/src/random-transaction.ts index ac475348e5..87d286fd28 100644 --- a/src/mina-signer/src/random-transaction.ts +++ b/src/mina-signer/src/random-transaction.ts @@ -141,7 +141,7 @@ const RandomTransaction = { zkappCommand, zkappCommandAndFeePayerKey, zkappCommandJson, - networkId: Random.oneOf('testnet', 'mainnet', { + networkId: Random.oneOf('testnet', 'mainnet', 'devnet', { custom: 'other', }), accountUpdateWithCallDepth: accountUpdate, diff --git a/src/mina-signer/src/sign-legacy.unit-test.ts b/src/mina-signer/src/sign-legacy.unit-test.ts index 3654943682..2a54a56cf2 100644 --- a/src/mina-signer/src/sign-legacy.unit-test.ts +++ b/src/mina-signer/src/sign-legacy.unit-test.ts @@ -23,7 +23,7 @@ import { RandomTransaction } from './random-transaction.js'; import { NetworkId } from './types.js'; let { privateKey, publicKey } = keypair; -let networks: NetworkId[] = ['testnet', 'mainnet']; +let networks: NetworkId[] = ['devnet', 'testnet', 'mainnet']; // test hard-coded cases against reference signature @@ -73,16 +73,26 @@ test( verifyPayment(payment, sig, publicKey, network); // valid signatures & verification matrix + let devnet = signPayment(payment, privateKey, 'devnet'); let testnet = signPayment(payment, privateKey, 'testnet'); let mainnet = signPayment(payment, privateKey, 'mainnet'); + assert(verify(devnet, 'testnet') === true); + assert(verify(testnet, 'devnet') === true); + assert(verify(testnet, 'testnet') === true); assert(verify(testnet, 'mainnet') === false); assert(verify(mainnet, 'testnet') === false); + + assert(verify(devnet, 'devnet') === true); + assert(verify(devnet, 'mainnet') === false); + assert(verify(mainnet, 'devnet') === false); assert(verify(mainnet, 'mainnet') === true); // fails when signing with wrong private key let testnetWrong = signPayment(payment, otherKey, 'testnet'); + let devnetWrong = signPayment(payment, otherKey, 'devnet'); let mainnetWrong = signPayment(payment, otherKey, 'mainnet'); + assert(verify(devnetWrong, 'devnet') === false); assert(verify(testnetWrong, 'testnet') === false); assert(verify(mainnetWrong, 'mainnet') === false); } diff --git a/src/mina-signer/src/sign-zkapp-command.unit-test.ts b/src/mina-signer/src/sign-zkapp-command.unit-test.ts index e0f1ccacdc..d833a6b5da 100644 --- a/src/mina-signer/src/sign-zkapp-command.unit-test.ts +++ b/src/mina-signer/src/sign-zkapp-command.unit-test.ts @@ -112,6 +112,12 @@ test( expect(hash).toEqual(hashSnarky.toBigInt()); // check against different network hash + expect(hash).not.toEqual( + accountUpdateHash( + accountUpdate, + NetworkId.toString(networkId) === 'mainnet' ? 'devnet' : 'mainnet' + ) + ); expect(hash).not.toEqual( accountUpdateHash( accountUpdate, @@ -262,6 +268,9 @@ test( expect( verify(sigFieldElements, networkId === 'mainnet' ? 'testnet' : 'mainnet') ).toEqual(false); + expect( + verify(sigFieldElements, networkId === 'mainnet' ? 'devnet' : 'mainnet') + ).toEqual(false); // full end-to-end test: sign a zkapp transaction let sig = signZkappCommand(zkappCommandJson, feePayerKeyBase58, networkId); @@ -278,6 +287,13 @@ test( networkId === 'mainnet' ? 'testnet' : 'mainnet' ) ).toEqual(false); + expect( + verifyZkappCommandSignature( + sig, + feePayerAddressBase58, + networkId === 'mainnet' ? 'devnet' : 'mainnet' + ) + ).toEqual(false); } ); diff --git a/src/mina-signer/src/signature.unit-test.ts b/src/mina-signer/src/signature.unit-test.ts index 64dc027cf1..98055fea85 100644 --- a/src/mina-signer/src/signature.unit-test.ts +++ b/src/mina-signer/src/signature.unit-test.ts @@ -42,6 +42,14 @@ function checkConsistentSingle( networkId === 'mainnet' ? 'testnet' : 'mainnet' ) ).toEqual(false); + expect( + verifyFieldElement( + sig, + msg, + pk, + networkId === 'mainnet' ? 'devnet' : 'mainnet' + ) + ).toEqual(false); // consistent with OCaml let msgMl = FieldConst.fromBigint(msg); diff --git a/src/mina-signer/src/test-vectors/legacySignatures.ts b/src/mina-signer/src/test-vectors/legacySignatures.ts index 7090587475..db17f153e9 100644 --- a/src/mina-signer/src/test-vectors/legacySignatures.ts +++ b/src/mina-signer/src/test-vectors/legacySignatures.ts @@ -91,6 +91,62 @@ let strings = [ * - the 3 strings. */ let signatures: { [k: string]: { field: string; scalar: string }[] } = { + devnet: [ + { + field: + '3925887987173883783388058255268083382298769764463609405200521482763932632383', + scalar: + '445615701481226398197189554290689546503290167815530435382795701939759548136', + }, + { + field: + '11838925242791061185900891854974280922359055483441419242429642295065318643984', + scalar: + '5057044820006008308046028014628135487302791372585541488835641418654652928805', + }, + { + field: + '13570419670106759824217358880396743605262660069048455950202130815805728575057', + scalar: + '2256128221267944805514947515637443480133552241968312777663034361688965989223', + }, + { + field: + '18603328765572408555868399359399411973012220541556204196884026585115374044583', + scalar: + '17076342019359061119005549736934690084415105419939473687106079907606137611470', + }, + { + field: + '1786373894608285187089973929748850875336413409295396991315429715474432640801', + scalar: + '10435258496141097615588833319454104720521911644724923418749752896069542389757', + }, + { + field: + '11710586766419351067338319607483640291676872446372400739329190129174446858072', + scalar: + '21663533922934564101122062377096487451020504743791218020915919810997397884837', + }, + { + field: + '11583775536286847540414661987230057163492736306749717851628536966882998258109', + scalar: + '14787360096063782022566783796923142259879388947509616216546009448340181956495', + }, + { + field: + '24809097509137086694730479515383937245108109696879845335879579016397403384488', + scalar: + '23723859937408726087117568974923795978435877847592289069941156359435022279156', + }, + { + field: + '23803497755408154859878117448681790665144834176143832235351783889976460433296', + scalar: + '21219917886278462345652813021708727397787183083051040637716760620250038837684', + }, + ], testnet: [ { field: From 53abba62067898155c086795e3b3e8e40deb7f38 Mon Sep 17 00:00:00 2001 From: hattyhattington17 <181872047+hattyhattington17@users.noreply.github.com> Date: Tue, 3 Dec 2024 16:35:13 -0700 Subject: [PATCH 266/328] update mina-signer tests to include devnet client --- src/mina-signer/tests/client.test.ts | 7 ++- src/mina-signer/tests/message.test.ts | 71 ++++++++++++++++++++++++++- 2 files changed, 75 insertions(+), 3 deletions(-) diff --git a/src/mina-signer/tests/client.test.ts b/src/mina-signer/tests/client.test.ts index 4ca384a2d2..e620429ee2 100644 --- a/src/mina-signer/tests/client.test.ts +++ b/src/mina-signer/tests/client.test.ts @@ -13,7 +13,12 @@ describe('Client Class Initialization', () => { expect(client).toBeDefined(); }); - it('should throw an error if a value that is not `mainnet` or `testnet` is specified', () => { + it('should accept `devnet` as a valid network parameter', () => { + client = new Client({ network: 'devnet' }); + expect(client).toBeDefined(); + }); + + it('should throw an error if a value that is not `mainnet`, `devnet`, or `testnet` is specified', () => { try { //@ts-ignore client = new Client({ network: 'new-network' }); diff --git a/src/mina-signer/tests/message.test.ts b/src/mina-signer/tests/message.test.ts index bd9586fb19..451972f1b5 100644 --- a/src/mina-signer/tests/message.test.ts +++ b/src/mina-signer/tests/message.test.ts @@ -37,6 +37,14 @@ describe('Message', () => { expect(client.verifyTransaction(message)).toEqual(true); }); + it('does not verify a signed message from `devnet`', () => { + const message = client.signMessage('hello', privateKey); + const devnetClient = new Client({ network: 'devnet' }); + const invalidMessage = devnetClient.verifyMessage(message); + expect(invalidMessage).toBeFalsy(); + expect(devnetClient.verifyTransaction(message)).toEqual(false); + }); + it('does not verify a signed message from `testnet`', () => { const message = client.signMessage('hello', privateKey); const testnetClient = new Client({ network: 'testnet' }); @@ -46,12 +54,12 @@ describe('Message', () => { }); }); - describe('Testnet network', () => { + describe('Devnet network', () => { let client: Client; let privateKey: PrivateKey; beforeAll(async () => { - client = new Client({ network: 'testnet' }); + client = new Client({ network: 'devnet' }); ({ privateKey } = client.genKeys()); }); @@ -89,4 +97,63 @@ describe('Message', () => { expect(mainnetClient.verifyTransaction(message)).toEqual(false); }); }); + + describe('Testnet network', () => { + let testnetClient: Client; + let devnetClient: Client; + let privateKey: PrivateKey; + + beforeAll(async () => { + testnetClient = new Client({ network: 'testnet' }); + devnetClient = new Client({ network: 'devnet' }); + ({ privateKey } = devnetClient.genKeys()); + }); + + it('generates the same signatures as devnet', () => { + const testnetMessage = testnetClient.signMessage('hello', privateKey); + const devnetMessage = devnetClient.signMessage('hello', privateKey); + expect(testnetMessage).toEqual(devnetMessage); + }); + + + it('generates the same signatures as devnet using signTransaction', () => { + const testnetMessage = testnetClient.signTransaction('hello', privateKey); + const devnetMessage = devnetClient.signTransaction('hello', privateKey); + expect(testnetMessage).toEqual(devnetMessage); + }); + + it('verifies a signed message from devnet and vice versa', () => { + const testnetMessage = testnetClient.signMessage('hello', privateKey); + const devnetMessage = devnetClient.signMessage('hello', privateKey); + + const verifiedDevnetMessage = testnetClient.verifyMessage(devnetMessage); + const verifiedTestnetMessage = devnetClient.verifyMessage(testnetMessage); + expect(verifiedDevnetMessage).toBeTruthy(); + expect(verifiedTestnetMessage).toBeTruthy(); + + expect(testnetClient.verifyTransaction(devnetMessage)).toEqual(true); + expect(devnetClient.verifyTransaction(testnetMessage)).toEqual(true); + }); + + it('verifies a signed message generated by signTransaction from devnet and vice versa', () => { + const testnetMessage = testnetClient.signTransaction('hello', privateKey); + const devnetMessage = devnetClient.signTransaction('hello', privateKey); + + const verifiedDevnetMessage = testnetClient.verifyMessage(devnetMessage); + const verifiedTestnetMessage = devnetClient.verifyMessage(testnetMessage); + expect(verifiedDevnetMessage).toBeTruthy(); + expect(verifiedTestnetMessage).toBeTruthy(); + + expect(testnetClient.verifyTransaction(devnetMessage)).toEqual(true); + expect(devnetClient.verifyTransaction(testnetMessage)).toEqual(true); + }); + + it('does not verify a signed message from `mainnet`', () => { + const message = testnetClient.signMessage('hello', privateKey); + const mainnetClient = new Client({ network: 'mainnet' }); + const invalidMessage = mainnetClient.verifyMessage(message); + expect(invalidMessage).toBeFalsy(); + expect(mainnetClient.verifyTransaction(message)).toEqual(false); + }); + }); }); From 18faf8808cbbdc21e0357b879f3f1fa070beaad1 Mon Sep 17 00:00:00 2001 From: Florian Date: Wed, 4 Dec 2024 18:50:48 +0700 Subject: [PATCH 267/328] changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f895921488..46f96c522a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,8 +22,8 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm -`ZkProgram` to support non-pure provable types as inputs and outputs https://github.com/o1-labs/o1js/pull/1828 - Add `enforceTransactionLimits` parameter on Network https://github.com/o1-labs/o1js/issues/1910 - - Method for optional types to assert none https://github.com/o1-labs/o1js/pull/1922 +- Increased maximum supported amount of methods in a `SmartContract` or `ZkProgram` to 30. https://github.com/o1-labs/o1js/pull/1918 ### Fixed From 686c085f4493b301784331e0f5b2dbaf5250fafc Mon Sep 17 00:00:00 2001 From: Florian Date: Wed, 4 Dec 2024 19:46:07 +0700 Subject: [PATCH 268/328] fix changelog merge conflict --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 46f96c522a..41aacd8288 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Add `enforceTransactionLimits` parameter on Network https://github.com/o1-labs/o1js/issues/1910 - Method for optional types to assert none https://github.com/o1-labs/o1js/pull/1922 - Increased maximum supported amount of methods in a `SmartContract` or `ZkProgram` to 30. https://github.com/o1-labs/o1js/pull/1918 +- Expose low-level conversion methods `Proof.{_proofToBase64,_proofFromBase64}` https://github.com/o1-labs/o1js/pull/1928 ### Fixed From ddb1d66c0fc8c85a53eb8794b8ba400d98cea0c8 Mon Sep 17 00:00:00 2001 From: hattyhattington17 <181872047+hattyhattington17@users.noreply.github.com> Date: Wed, 4 Dec 2024 07:54:06 -0700 Subject: [PATCH 269/328] add tests for devnet mina-signer --- src/mina-signer/src/signature.unit-test.ts | 4 +- src/mina-signer/tests/message.test.ts | 2 +- src/mina-signer/tests/payment.test.ts | 208 +++++++++++++++++- .../tests/stake-delegation.test.ts | 130 ++++++++++- src/mina-signer/tests/zkapp.unit-test.ts | 2 +- 5 files changed, 340 insertions(+), 6 deletions(-) diff --git a/src/mina-signer/src/signature.unit-test.ts b/src/mina-signer/src/signature.unit-test.ts index 98055fea85..3bd81efcd3 100644 --- a/src/mina-signer/src/signature.unit-test.ts +++ b/src/mina-signer/src/signature.unit-test.ts @@ -33,7 +33,7 @@ function checkConsistentSingle( // verify expect(verifyFieldElement(sig, msg, pk, networkId)).toEqual(true); - // verify against different network + // if the signature was generated with networkId=mainnet, the signature should not verify against testnet or devnet expect( verifyFieldElement( sig, @@ -118,6 +118,7 @@ for (let i = 0; i < 10; i++) { // hard coded single field elements let hardcoded = [0n, 1n, 2n, p - 1n]; for (let x of hardcoded) { + checkConsistentSingle(x, key, keySnarky, publicKey, 'devnet'); checkConsistentSingle(x, key, keySnarky, publicKey, 'testnet'); checkConsistentSingle(x, key, keySnarky, publicKey, 'mainnet'); checkConsistentSingle(x, key, keySnarky, publicKey, { custom: 'other' }); @@ -125,6 +126,7 @@ for (let i = 0; i < 10; i++) { // random single field elements for (let i = 0; i < 10; i++) { let x = randomFields[i]; + checkConsistentSingle(x, key, keySnarky, publicKey, 'devnet'); checkConsistentSingle(x, key, keySnarky, publicKey, 'testnet'); checkConsistentSingle(x, key, keySnarky, publicKey, 'mainnet'); checkConsistentSingle(x, key, keySnarky, publicKey, { custom: 'other' }); diff --git a/src/mina-signer/tests/message.test.ts b/src/mina-signer/tests/message.test.ts index 451972f1b5..0b5b6f6fd2 100644 --- a/src/mina-signer/tests/message.test.ts +++ b/src/mina-signer/tests/message.test.ts @@ -134,7 +134,7 @@ describe('Message', () => { expect(testnetClient.verifyTransaction(devnetMessage)).toEqual(true); expect(devnetClient.verifyTransaction(testnetMessage)).toEqual(true); }); - + it('verifies a signed message generated by signTransaction from devnet and vice versa', () => { const testnetMessage = testnetClient.signTransaction('hello', privateKey); const devnetMessage = devnetClient.signTransaction('hello', privateKey); diff --git a/src/mina-signer/tests/payment.test.ts b/src/mina-signer/tests/payment.test.ts index de84939d67..34fbf24abe 100644 --- a/src/mina-signer/tests/payment.test.ts +++ b/src/mina-signer/tests/payment.test.ts @@ -103,6 +103,23 @@ describe('Payment', () => { expect(hashedPayment).toBeDefined(); }); + it('does not verify a signed payment from `devnet`', () => { + const payment = client.signPayment( + { + to: keypair.publicKey, + from: keypair.publicKey, + amount: '1', + fee: '1', + nonce: '0', + }, + keypair.privateKey + ); + const devnetClient = new Client({ network: 'devnet' }); + const invalidPayment = devnetClient.verifyPayment(payment); + expect(invalidPayment).toBeFalsy(); + expect(devnetClient.verifyTransaction(payment)).toEqual(false); + }); + it('does not verify a signed payment from `testnet`', () => { const payment = client.signPayment( { @@ -121,12 +138,12 @@ describe('Payment', () => { }); }); - describe('Testnet network', () => { + describe('Devnet network', () => { let client: Client; let keypair: Keypair; beforeAll(async () => { - client = new Client({ network: 'testnet' }); + client = new Client({ network: 'devnet' }); keypair = client.genKeys(); }); @@ -239,4 +256,191 @@ describe('Payment', () => { expect(mainnetClient.verifyTransaction(payment)).toEqual(false); }); }); + describe('Testnet network', () => { + let testnetClient: Client; + let devnetClient: Client; + let keypair: Keypair; + + beforeAll(async () => { + testnetClient = new Client({ network: 'testnet' }); + devnetClient = new Client({ network: 'devnet' }); + keypair = testnetClient.genKeys(); + }); + + it('generates the same signed payment as devnet', () => { + const testnetPayment = testnetClient.signPayment( + { + to: keypair.publicKey, + from: keypair.publicKey, + amount: '1', + fee: '1', + nonce: '0', + }, + keypair.privateKey + ); + const devnetPayment = devnetClient.signPayment( + { + to: keypair.publicKey, + from: keypair.publicKey, + amount: '1', + fee: '1', + nonce: '0', + }, + keypair.privateKey + ); + expect(testnetPayment).toEqual(devnetPayment); + }); + + it('generates the same signed transaction by using signTransaction as a devnet client', () => { + const testnetTransaction = testnetClient.signTransaction( + { + to: keypair.publicKey, + from: keypair.publicKey, + amount: '1', + fee: '1', + nonce: '0', + }, + keypair.privateKey + ); + const devnetTransaction = devnetClient.signTransaction( + { + to: keypair.publicKey, + from: keypair.publicKey, + amount: '1', + fee: '1', + nonce: '0', + }, + keypair.privateKey + ); + expect(testnetTransaction).toEqual(devnetTransaction); + }); + + it('devnet client verifies a signed testnet payment and vice versa', () => { + const testnetPayment = testnetClient.signPayment( + { + to: keypair.publicKey, + from: keypair.publicKey, + amount: '1', + fee: '1', + nonce: '0', + }, + keypair.privateKey + ); + const devnetPayment = devnetClient.signPayment( + { + to: keypair.publicKey, + from: keypair.publicKey, + amount: '1', + fee: '1', + nonce: '0', + }, + keypair.privateKey + ); + const verifiedDevnetPayment = testnetClient.verifyPayment(devnetPayment); + expect(verifiedDevnetPayment).toBeTruthy(); + expect(testnetClient.verifyTransaction(devnetPayment)).toEqual(true); + + const verifiedTestnetPayment = devnetClient.verifyPayment(testnetPayment); + expect(verifiedTestnetPayment).toBeTruthy(); + expect(devnetClient.verifyTransaction(testnetPayment)).toEqual(true); + }); + it('devnet client verifies a signed testnet payment generated with signTransaction and vice versa', () => { + const testnetPayment = testnetClient.signTransaction( + { + to: keypair.publicKey, + from: keypair.publicKey, + amount: '1', + fee: '1', + nonce: '0', + }, + keypair.privateKey + ); + const devnetPayment = devnetClient.signTransaction( + { + to: keypair.publicKey, + from: keypair.publicKey, + amount: '1', + fee: '1', + nonce: '0', + }, + keypair.privateKey + ); + const verifiedDevnetPayment = testnetClient.verifyPayment(devnetPayment); + expect(verifiedDevnetPayment).toBeTruthy(); + expect(testnetClient.verifyTransaction(devnetPayment)).toEqual(true); + + const verifiedTestnetPayment = devnetClient.verifyPayment(testnetPayment); + expect(verifiedTestnetPayment).toBeTruthy(); + expect(devnetClient.verifyTransaction(testnetPayment)).toEqual(true); + }); + + it('generates same signed payment hash as devnet', () => { + const testnetPayment = testnetClient.signPayment( + { + to: keypair.publicKey, + from: keypair.publicKey, + amount: '1', + fee: '1', + nonce: '0', + }, + keypair.privateKey + ); + const hashedTestnetPayment = testnetClient.hashPayment(testnetPayment); + const devnetPayment = devnetClient.signPayment( + { + to: keypair.publicKey, + from: keypair.publicKey, + amount: '1', + fee: '1', + nonce: '0', + }, + keypair.privateKey + ); + const hashedDevnetPayment = devnetClient.hashPayment(devnetPayment); + expect(hashedTestnetPayment).toEqual(hashedDevnetPayment); + }); + + it('generates same signed payment hash as devnet for payment generated with signTransaction', () => { + const testnetPayment = testnetClient.signTransaction( + { + to: keypair.publicKey, + from: keypair.publicKey, + amount: '1', + fee: '1', + nonce: '0', + }, + keypair.privateKey + ); + const hashedTestnetPayment = testnetClient.hashPayment(testnetPayment); + const devnetPayment = devnetClient.signTransaction( + { + to: keypair.publicKey, + from: keypair.publicKey, + amount: '1', + fee: '1', + nonce: '0', + }, + keypair.privateKey + ); + const hashedDevnetPayment = devnetClient.hashPayment(devnetPayment); + expect(hashedTestnetPayment).toEqual(hashedDevnetPayment); + }); + + it('does not verify a signed payment from `mainnet`', () => { + const payment = testnetClient.signPayment( + { + to: keypair.publicKey, + from: keypair.publicKey, + amount: '1', + fee: '1', + nonce: '0', + }, + keypair.privateKey + ); + const mainnetClient = new Client({ network: 'mainnet' }); + const invalidPayment = mainnetClient.verifyPayment(payment); + expect(invalidPayment).toBeFalsy(); + expect(mainnetClient.verifyTransaction(payment)).toEqual(false); + }); + }); }); diff --git a/src/mina-signer/tests/stake-delegation.test.ts b/src/mina-signer/tests/stake-delegation.test.ts index 16cdf0d8f6..58d273040c 100644 --- a/src/mina-signer/tests/stake-delegation.test.ts +++ b/src/mina-signer/tests/stake-delegation.test.ts @@ -114,7 +114,7 @@ describe('Stake Delegation', () => { }); }); - describe('Testnet network', () => { + describe('Devnet network', () => { let client: Client; let keypair: Keypair; @@ -211,4 +211,132 @@ describe('Stake Delegation', () => { expect(mainnetClient.verifyTransaction(delegation)).toEqual(false); }); }); + describe('Testnet network', () => { + let testnetClient: Client; + let devnetClient: Client; + let keypair: Keypair; + + beforeAll(async () => { + testnetClient = new Client({ network: 'testnet' }); + devnetClient = new Client({ network: 'devnet' }); + keypair = testnetClient.genKeys(); + }); + + it('generates the same signed stake delegation as devnet', () => { + const testnetDelegation = testnetClient.signStakeDelegation( + { + to: keypair.publicKey, + from: keypair.publicKey, + fee: '1', + nonce: '0', + }, + keypair.privateKey + ); + const devnetDelegation = testnetClient.signStakeDelegation( + { + to: keypair.publicKey, + from: keypair.publicKey, + fee: '1', + nonce: '0', + }, + keypair.privateKey + ); + expect(testnetDelegation).toEqual(devnetDelegation); + }); + it('generates the same signed stake delegation as devnet using signTransaction', () => { + const testnetDelegation = testnetClient.signTransaction( + { + to: keypair.publicKey, + from: keypair.publicKey, + fee: '1', + nonce: '0', + }, + keypair.privateKey + ); + const devnetDelegation = testnetClient.signTransaction( + { + to: keypair.publicKey, + from: keypair.publicKey, + fee: '1', + nonce: '0', + }, + keypair.privateKey + ); + expect(testnetDelegation).toEqual(devnetDelegation); + }); + + + it('verifies a signed delegation from devnet and vice versa', () => { + const testnetDelegation = testnetClient.signStakeDelegation( + { + to: keypair.publicKey, + from: keypair.publicKey, + fee: '1', + nonce: '0', + }, + keypair.privateKey + ); + const devnetDelegation = testnetClient.signStakeDelegation( + { + to: keypair.publicKey, + from: keypair.publicKey, + fee: '1', + nonce: '0', + }, + keypair.privateKey + ); + const verifiedDevnetDelegation = testnetClient.verifyStakeDelegation(devnetDelegation); + expect(verifiedDevnetDelegation).toBeTruthy(); + expect(testnetClient.verifyTransaction(devnetDelegation)).toEqual(true); + + const verifiedTestnetDelegation = devnetClient.verifyStakeDelegation(testnetDelegation); + expect(verifiedTestnetDelegation).toBeTruthy(); + expect(devnetClient.verifyTransaction(testnetDelegation)).toEqual(true); + }); + + + it('verifies a signed delegation generated by signTransaction from devnet and vice versa', () => { + const testnetDelegation = testnetClient.signTransaction( + { + to: keypair.publicKey, + from: keypair.publicKey, + fee: '1', + nonce: '0', + }, + keypair.privateKey + ); + const devnetDelegation = testnetClient.signTransaction( + { + to: keypair.publicKey, + from: keypair.publicKey, + fee: '1', + nonce: '0', + }, + keypair.privateKey + ); + const verifiedDevnetDelegation = testnetClient.verifyStakeDelegation(devnetDelegation); + expect(verifiedDevnetDelegation).toBeTruthy(); + expect(testnetClient.verifyTransaction(devnetDelegation)).toEqual(true); + + const verifiedTestnetDelegation = devnetClient.verifyStakeDelegation(testnetDelegation); + expect(verifiedTestnetDelegation).toBeTruthy(); + expect(devnetClient.verifyTransaction(testnetDelegation)).toEqual(true); + }); + + it('does not verify a signed message from `mainnet`', () => { + const delegation = testnetClient.signStakeDelegation( + { + to: keypair.publicKey, + from: keypair.publicKey, + fee: '1', + nonce: '0', + }, + keypair.privateKey + ); + const mainnetClient = new Client({ network: 'mainnet' }); + const invalidMessage = mainnetClient.verifyStakeDelegation(delegation); + expect(invalidMessage).toBeFalsy(); + expect(mainnetClient.verifyTransaction(delegation)).toEqual(false); + }); + }); }); diff --git a/src/mina-signer/tests/zkapp.unit-test.ts b/src/mina-signer/tests/zkapp.unit-test.ts index 1b3ffb66c3..6580df4a8c 100644 --- a/src/mina-signer/tests/zkapp.unit-test.ts +++ b/src/mina-signer/tests/zkapp.unit-test.ts @@ -8,7 +8,7 @@ import { PrivateKey } from '../../lib/provable/crypto/signature.js'; import { Signature } from '../src/signature.js'; import { mocks } from '../../bindings/crypto/constants.js'; -const client = new Client({ network: 'testnet' }); +const client = new Client({ network: 'devnet' }); let { publicKey, privateKey } = client.genKeys(); let dummy = ZkappCommand.toJSON(ZkappCommand.empty()); From 74b9fe8e6bb0d0c91f32227320bc415034f985de Mon Sep 17 00:00:00 2001 From: Geometer1729 <16kuhnb@gmail.com> Date: Wed, 4 Dec 2024 09:55:55 -0500 Subject: [PATCH 270/328] update bindings --- flake.lock | 4 ++-- src/bindings | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 9b7d4e5d7f..8212b48e9e 100644 --- a/flake.lock +++ b/flake.lock @@ -265,8 +265,8 @@ "utils": "utils" }, "locked": { - "lastModified": 1732222139, - "narHash": "sha256-4LLy5VMM5TK4LpQXEBiA8ziwYyqGx2ZAuunXGCDpraQ=", + "lastModified": 1733261591, + "narHash": "sha256-1gbcNmug8xmcWM6QEUA3BkgSVWIpjAiT8SouiEu6gQg=", "path": "src/mina", "type": "path" }, diff --git a/src/bindings b/src/bindings index fec4c019ef..bd373a5955 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit fec4c019ef178e570482e72ee8b1a5530b81c3ff +Subproject commit bd373a5955072dbad12069dd21bbf8e6a7fad7e4 From 79cc40fa698d08aaa99397542cb286b90c5e35cf Mon Sep 17 00:00:00 2001 From: Geometer1729 <16kuhnb@gmail.com> Date: Wed, 4 Dec 2024 10:49:29 -0500 Subject: [PATCH 271/328] merge bindings --- src/bindings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bindings b/src/bindings index bd373a5955..51f5e4dc04 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit bd373a5955072dbad12069dd21bbf8e6a7fad7e4 +Subproject commit 51f5e4dc04acafe6ac2f127ae1d1701369587671 From fa811ab3560c907e73b2f7eca025644c85e9114e Mon Sep 17 00:00:00 2001 From: hattyhattington17 <181872047+hattyhattington17@users.noreply.github.com> Date: Wed, 4 Dec 2024 09:05:52 -0700 Subject: [PATCH 272/328] update bindings to accept devnet as string network id --- CHANGELOG.md | 1 + generate-keys.js | 2 +- src/bindings | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f895921488..83e2ee810c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Compiling stuck in the browser for recursive zkprograms https://github.com/o1-labs/o1js/pull/1906 - Error message in `rangeCheck16` gadget https://github.com/o1-labs/o1js/pull/1920 +- Deprecate `testnet` `networkId` in favor of `devnet` https://github.com/o1-labs/o1js/pull/1938 ## [2.1.0](https://github.com/o1-labs/o1js/compare/b04520d...e1bac02) - 2024-11-13 diff --git a/generate-keys.js b/generate-keys.js index b702948882..b638d116a7 100755 --- a/generate-keys.js +++ b/generate-keys.js @@ -1,6 +1,6 @@ #!/usr/bin/env node import Client from './dist/node/mina-signer/mina-signer.js'; -let client = new Client({ network: 'testnet' }); +let client = new Client({ network: 'devnet' }); console.log(client.genKeys()); diff --git a/src/bindings b/src/bindings index 2c62a9a755..317c73252b 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit 2c62a9a755f1b128f89cc2131814df7157f68109 +Subproject commit 317c73252b85702570ca95e85943cf749727074c From 8738e65defc75f5543db635f9c0c1f84e7ee0e00 Mon Sep 17 00:00:00 2001 From: Geometer1729 <16kuhnb@gmail.com> Date: Wed, 4 Dec 2024 11:59:20 -0500 Subject: [PATCH 273/328] add gc root when on main --- .github/workflows/build-bindings.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-bindings.yml b/.github/workflows/build-bindings.yml index 73d2661566..2c24084115 100644 --- a/.github/workflows/build-bindings.yml +++ b/.github/workflows/build-bindings.yml @@ -31,9 +31,11 @@ jobs: #fail if this changes any files cd src/bindings git diff --exit-code + - name: add build to gc-root if on main + if: github.ref == 'refs/heads/main' + run: | + nix build o1js#o1js-bindings --out-link /var/o1js-bindings-gcroot - name: Cleanup the Nix store run: | - nix-env --delete-generations old - nix-collect-garbage -d --quiet nix-store --gc --print-dead nix-store --optimise From dfe49095ec46d95890e2f963fe33a8203281c21f Mon Sep 17 00:00:00 2001 From: Geometer1729 <16kuhnb@gmail.com> Date: Wed, 4 Dec 2024 12:41:37 -0500 Subject: [PATCH 274/328] test gc-root --- .github/workflows/build-bindings.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-bindings.yml b/.github/workflows/build-bindings.yml index 2c24084115..d1c9d5a899 100644 --- a/.github/workflows/build-bindings.yml +++ b/.github/workflows/build-bindings.yml @@ -32,9 +32,10 @@ jobs: cd src/bindings git diff --exit-code - name: add build to gc-root if on main - if: github.ref == 'refs/heads/main' + # enabeling on this branch for 1 commit to test it + #if: github.ref == 'refs/heads/main' run: | - nix build o1js#o1js-bindings --out-link /var/o1js-bindings-gcroot + nix build o1js#o1js-bindings --out-link /home/app/actions-runner/nix-cache/main-bindings-gcroot - name: Cleanup the Nix store run: | nix-store --gc --print-dead From 70ca77d7c0a63acf84557c34784fc1c8391ca34f Mon Sep 17 00:00:00 2001 From: Geometer1729 <16kuhnb@gmail.com> Date: Wed, 4 Dec 2024 18:35:05 -0500 Subject: [PATCH 275/328] back gc-root only for main --- .github/workflows/build-bindings.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-bindings.yml b/.github/workflows/build-bindings.yml index d1c9d5a899..f5d92f8385 100644 --- a/.github/workflows/build-bindings.yml +++ b/.github/workflows/build-bindings.yml @@ -33,7 +33,7 @@ jobs: git diff --exit-code - name: add build to gc-root if on main # enabeling on this branch for 1 commit to test it - #if: github.ref == 'refs/heads/main' + if: github.ref == 'refs/heads/main' run: | nix build o1js#o1js-bindings --out-link /home/app/actions-runner/nix-cache/main-bindings-gcroot - name: Cleanup the Nix store From 96a17d77e688e9d8675f9e0fbc60fdbd958d8d62 Mon Sep 17 00:00:00 2001 From: Geometer1729 <16kuhnb@gmail.com> Date: Thu, 5 Dec 2024 13:35:44 -0500 Subject: [PATCH 276/328] update mina --- flake.lock | 4 ++-- src/bindings | 2 +- src/mina | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/flake.lock b/flake.lock index 8212b48e9e..97819c6505 100644 --- a/flake.lock +++ b/flake.lock @@ -265,8 +265,8 @@ "utils": "utils" }, "locked": { - "lastModified": 1733261591, - "narHash": "sha256-1gbcNmug8xmcWM6QEUA3BkgSVWIpjAiT8SouiEu6gQg=", + "lastModified": 1733421256, + "narHash": "sha256-X7sT6cQ7X2V5A/Q8FOnc0pDP24gca/FOMszeWRiC2mM=", "path": "src/mina", "type": "path" }, diff --git a/src/bindings b/src/bindings index 51f5e4dc04..68f63f577a 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit 51f5e4dc04acafe6ac2f127ae1d1701369587671 +Subproject commit 68f63f577a4673fdf1f47796330df329ffbafc0e diff --git a/src/mina b/src/mina index f820d28f01..a8ddeab40a 160000 --- a/src/mina +++ b/src/mina @@ -1 +1 @@ -Subproject commit f820d28f011f709af564aec5d93db07c761a948c +Subproject commit a8ddeab40adf1412b98aec78508d1df38821c6bc From 7842a518e409ac5fc024a2ba0dd23f00f87f984f Mon Sep 17 00:00:00 2001 From: Geometer1729 <16kuhnb@gmail.com> Date: Thu, 5 Dec 2024 13:53:02 -0500 Subject: [PATCH 277/328] update bindings --- src/bindings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bindings b/src/bindings index 68f63f577a..8afb480177 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit 68f63f577a4673fdf1f47796330df329ffbafc0e +Subproject commit 8afb4801776db2bb58487e75b7586af01731e589 From 4b926eaee1ad706550d7c064209dd34ce51a4072 Mon Sep 17 00:00:00 2001 From: hattyhattington17 <181872047+hattyhattington17@users.noreply.github.com> Date: Thu, 5 Dec 2024 12:17:58 -0700 Subject: [PATCH 278/328] remove testnet from comment --- src/mina-signer/src/signature.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mina-signer/src/signature.ts b/src/mina-signer/src/signature.ts index 64df48d994..784927e4ca 100644 --- a/src/mina-signer/src/signature.ts +++ b/src/mina-signer/src/signature.ts @@ -111,7 +111,7 @@ function verifyFieldElement( * @param privateKey The `privateKey` represents an element of the Pallas scalar field, and should be given as a native bigint. * It can be converted from the base58 string representation using {@link PrivateKey.fromBase58}. * - * @param networkId The `networkId` is either "devnet"/"testnet" or "mainnet" and ensures that testnet transactions can + * @param networkId The `networkId` is either "devnet" or "mainnet" and ensures that testnet transactions can * never be used as valid mainnet transactions. * * @see {@link deriveNonce} and {@link hashMessage} for details on how the nonce and hash are computed. From c9857cc508241364a6387d7d5a2f4266b540b089 Mon Sep 17 00:00:00 2001 From: Geometer1729 <16kuhnb@gmail.com> Date: Thu, 5 Dec 2024 14:35:29 -0500 Subject: [PATCH 279/328] update+rebuild upgrade mina --- flake.lock | 4 ++-- src/bindings | 2 +- src/mina | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/flake.lock b/flake.lock index 97819c6505..565e258b45 100644 --- a/flake.lock +++ b/flake.lock @@ -265,8 +265,8 @@ "utils": "utils" }, "locked": { - "lastModified": 1733421256, - "narHash": "sha256-X7sT6cQ7X2V5A/Q8FOnc0pDP24gca/FOMszeWRiC2mM=", + "lastModified": 1733427826, + "narHash": "sha256-geJjdLW0yIjrYdgTECVWx4yDuFA6/4YDqncVQQ5e1ac=", "path": "src/mina", "type": "path" }, diff --git a/src/bindings b/src/bindings index 8afb480177..dcea53ebf1 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit 8afb4801776db2bb58487e75b7586af01731e589 +Subproject commit dcea53ebf14770f5b5c0f57ed074fff9ce0a54b2 diff --git a/src/mina b/src/mina index a8ddeab40a..b6f5f579c7 160000 --- a/src/mina +++ b/src/mina @@ -1 +1 @@ -Subproject commit a8ddeab40adf1412b98aec78508d1df38821c6bc +Subproject commit b6f5f579c78bd9b4b6ab44b666a9183f74a360fa From 4b074117900f3e5d823ea20db7b47d584439aea4 Mon Sep 17 00:00:00 2001 From: Gregor Date: Thu, 5 Dec 2024 21:14:42 +0100 Subject: [PATCH 280/328] feedback: more explicit type names in DeclaredProof --- src/lib/proof-system/proof.ts | 4 ++-- src/lib/proof-system/zkprogram-context.ts | 4 ++-- src/lib/proof-system/zkprogram.ts | 20 +++++++++++--------- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/lib/proof-system/proof.ts b/src/lib/proof-system/proof.ts index 6dcdea4cd1..8d96dad0f6 100644 --- a/src/lib/proof-system/proof.ts +++ b/src/lib/proof-system/proof.ts @@ -55,8 +55,8 @@ class ProofBase { */ declare() { if (!ZkProgramContext.has()) return false; - const Proof = this.constructor as Subclass; - ZkProgramContext.declareProof({ Proof, proof: this }); + const ProofClass = this.constructor as Subclass; + ZkProgramContext.declareProof({ ProofClass, proofInstance: this }); return true; } diff --git a/src/lib/proof-system/zkprogram-context.ts b/src/lib/proof-system/zkprogram-context.ts index f6b66f6459..e67787695e 100644 --- a/src/lib/proof-system/zkprogram-context.ts +++ b/src/lib/proof-system/zkprogram-context.ts @@ -5,8 +5,8 @@ import type { ProofBase } from './proof.js'; export { ZkProgramContext, DeclaredProof }; type DeclaredProof = { - Proof: Subclass>; - proof: ProofBase; + ProofClass: Subclass>; + proofInstance: ProofBase; }; type ZkProgramContext = { proofs: DeclaredProof[]; diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index d6d5c3bb36..1e3e7a9bb1 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -857,7 +857,9 @@ async function analyzeMethod( return method(...args); return method(publicInput, ...args); }); - proofs = ZkProgramContext.getDeclaredProofs().map(({ Proof }) => Proof); + proofs = ZkProgramContext.getDeclaredProofs().map( + ({ ProofClass }) => ProofClass + ); } finally { ZkProgramContext.leave(id); } @@ -946,8 +948,8 @@ function picklesRuleFromFunction( // extract proof statements for Pickles let previousStatements = proofs.map( - ({ proof }): Pickles.Statement => { - let fields = proof.publicFields(); + ({ proofInstance }): Pickles.Statement => { + let fields = proofInstance.publicFields(); let input = MlFieldArray.to(fields.input); let output = MlFieldArray.to(fields.output); return MlPair(input, output); @@ -955,13 +957,13 @@ function picklesRuleFromFunction( ); // handle dynamic proofs - proofs.forEach(({ Proof, proof }) => { - if (!(proof instanceof DynamicProof)) return; + proofs.forEach(({ ProofClass, proofInstance }) => { + if (!(proofInstance instanceof DynamicProof)) return; // Initialize side-loaded verification key - const tag = Proof.tag(); + const tag = ProofClass.tag(); const computedTag = SideloadedTag.get(tag.name); - const vk = proof.usedVerificationKey; + const vk = proofInstance.usedVerificationKey; if (vk === undefined) { throw new Error( @@ -1010,9 +1012,9 @@ function picklesRuleFromFunction( return { publicOutput: MlFieldArray.to(publicOutput), previousStatements: MlArray.to(previousStatements), - previousProofs: MlArray.to(proofs.map(({ proof }) => proof.proof)), + previousProofs: MlArray.to(proofs.map((p) => p.proofInstance.proof)), shouldVerify: MlArray.to( - proofs.map((proof) => proof.proof.shouldVerify.toField().value) + proofs.map((proof) => proof.proofInstance.shouldVerify.toField().value) ), }; } From 813a10eba73dde38bf941f95085eac6af2551ff8 Mon Sep 17 00:00:00 2001 From: Gregor Date: Thu, 5 Dec 2024 21:22:08 +0100 Subject: [PATCH 281/328] feedback: add code comments --- src/lib/proof-system/zkprogram.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 1e3e7a9bb1..094e144ba5 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -376,6 +376,9 @@ function ZkProgram< } } + // for each of the methods, create a prover function. + // in the first step, these are "regular" in that they always expect the public input as the first argument, + // which is easier to use internally. type RegularProver = ( publicInput: PublicInput, ...args: PrivateInputs[K] @@ -470,6 +473,8 @@ function ZkProgram< } let regularProvers = mapToObject(methodKeys, toRegularProver); + // wrap "regular" provers to remove an `undefined` public input argument, + // this matches how the method itself was defined in the case of no public input type Prover_ = Prover< PublicInput, PublicOutput, From 104387393657ce04787b8278d2f2467ebb54365b Mon Sep 17 00:00:00 2001 From: Geometer1729 <16kuhnb@gmail.com> Date: Thu, 5 Dec 2024 15:30:26 -0500 Subject: [PATCH 282/328] downgrade mina --- flake.lock | 4 ++-- src/bindings | 2 +- src/mina | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/flake.lock b/flake.lock index 565e258b45..49061b3547 100644 --- a/flake.lock +++ b/flake.lock @@ -265,8 +265,8 @@ "utils": "utils" }, "locked": { - "lastModified": 1733427826, - "narHash": "sha256-geJjdLW0yIjrYdgTECVWx4yDuFA6/4YDqncVQQ5e1ac=", + "lastModified": 1733429866, + "narHash": "sha256-/ZEGYdZ2hLjBwdEzG/BIjlDehOjuGWmBqzD55nXfZoY=", "path": "src/mina", "type": "path" }, diff --git a/src/bindings b/src/bindings index dcea53ebf1..181985212c 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit dcea53ebf14770f5b5c0f57ed074fff9ce0a54b2 +Subproject commit 181985212cd11d0f514a64f83d88490103e63d07 diff --git a/src/mina b/src/mina index b6f5f579c7..6899054b74 160000 --- a/src/mina +++ b/src/mina @@ -1 +1 @@ -Subproject commit b6f5f579c78bd9b4b6ab44b666a9183f74a360fa +Subproject commit 6899054b745c1323b9d5bcaa62c00bed2ad1ead3 From f591f02816c0e29bcc6a5caa7db951329a6dccae Mon Sep 17 00:00:00 2001 From: Gregor Date: Fri, 6 Dec 2024 16:18:29 +0100 Subject: [PATCH 283/328] zkprogram context fix --- src/lib/proof-system/zkprogram.ts | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 094e144ba5..5bff2a05fa 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -393,17 +393,25 @@ function ZkProgram< ): RegularProver { return async function prove_(publicInput, ...args) { if (!doProving) { - let { publicOutput, auxiliaryOutput } = - (hasPublicInput - ? await (methods[key].method as any)(publicInput, ...args) - : await (methods[key].method as any)(...args)) ?? {}; - - let proof = await SelfProof.dummy( - publicInput, - publicOutput, - await getMaxProofsVerified() - ); - return { proof, auxiliaryOutput }; + // we step into a ZkProgramContext here to match the context nesting + // that would happen if proofs were enabled -- otherwise, proofs declared + // in an inner program could be counted to the outer program + let id = ZkProgramContext.enter(); + try { + let { publicOutput, auxiliaryOutput } = + (hasPublicInput + ? await (methods[key].method as any)(publicInput, ...args) + : await (methods[key].method as any)(...args)) ?? {}; + + let proof = await SelfProof.dummy( + publicInput, + publicOutput, + await getMaxProofsVerified() + ); + return { proof, auxiliaryOutput }; + } finally { + ZkProgramContext.leave(id); + } } if (compileOutput === undefined) { From 5495399cc8004b9861c48b409e28345a68e5db63 Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Tue, 10 Dec 2024 00:06:20 +0000 Subject: [PATCH 284/328] 2.1.1 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index ab82906a48..e4fcbbed81 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "o1js", - "version": "2.1.0", + "version": "2.1.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "o1js", - "version": "2.1.0", + "version": "2.1.1", "license": "Apache-2.0", "dependencies": { "blakejs": "1.2.1", diff --git a/package.json b/package.json index e6043658ca..65745e34e3 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "o1js", "description": "TypeScript framework for zk-SNARKs and zkApps", - "version": "2.1.0", + "version": "2.1.1", "license": "Apache-2.0", "homepage": "https://github.com/o1-labs/o1js/", "repository": { From b8575161f8c19f1c3a2116ccdb2eeb2f03d4cae3 Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Tue, 10 Dec 2024 00:06:26 +0000 Subject: [PATCH 285/328] Update CHANGELOG for new version v2.1.1 --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 41aacd8288..b5d1a70765 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,9 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm _Security_ in case of vulnerabilities. --> -## [Unreleased](https://github.com/o1-labs/o1js/compare/e1bac02...HEAD) +## [Unreleased](https://github.com/o1-labs/o1js/compare/5495399cc...HEAD) + +## [2.1.1](https://github.com/o1-labs/o1js/compare/1ad7333e9e...5495399cc) - 2024-12-10 ### Added From 9d15a422c324c57cbde4c009327fc1df2796f539 Mon Sep 17 00:00:00 2001 From: Florian Date: Tue, 10 Dec 2024 19:25:31 +0700 Subject: [PATCH 286/328] fix version --- CHANGELOG.md | 5 ++--- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b5d1a70765..4a8e4d3908 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,12 +17,11 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ## [Unreleased](https://github.com/o1-labs/o1js/compare/5495399cc...HEAD) -## [2.1.1](https://github.com/o1-labs/o1js/compare/1ad7333e9e...5495399cc) - 2024-12-10 +## [2.2.0](https://github.com/o1-labs/o1js/compare/1ad7333e9e...5495399cc) - 2024-12-10 ### Added --`ZkProgram` to support non-pure provable types as inputs and outputs https://github.com/o1-labs/o1js/pull/1828 - +- `ZkProgram` to support non-pure provable types as inputs and outputs https://github.com/o1-labs/o1js/pull/1828 - Add `enforceTransactionLimits` parameter on Network https://github.com/o1-labs/o1js/issues/1910 - Method for optional types to assert none https://github.com/o1-labs/o1js/pull/1922 - Increased maximum supported amount of methods in a `SmartContract` or `ZkProgram` to 30. https://github.com/o1-labs/o1js/pull/1918 diff --git a/package-lock.json b/package-lock.json index e4fcbbed81..621dfa4837 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "o1js", - "version": "2.1.1", + "version": "2.2.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "o1js", - "version": "2.1.1", + "version": "2.2.0", "license": "Apache-2.0", "dependencies": { "blakejs": "1.2.1", diff --git a/package.json b/package.json index 65745e34e3..617bd77c7b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "o1js", "description": "TypeScript framework for zk-SNARKs and zkApps", - "version": "2.1.1", + "version": "2.2.0", "license": "Apache-2.0", "homepage": "https://github.com/o1-labs/o1js/", "repository": { From 65cc87f54b43ddf22cef735b150af608fa134d9a Mon Sep 17 00:00:00 2001 From: Florian Date: Tue, 10 Dec 2024 19:28:16 +0700 Subject: [PATCH 287/328] commit --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a8e4d3908..8cbaa37616 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,9 +15,9 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm _Security_ in case of vulnerabilities. --> -## [Unreleased](https://github.com/o1-labs/o1js/compare/5495399cc...HEAD) +## [Unreleased](https://github.com/o1-labs/o1js/compare/b857516...HEAD) -## [2.2.0](https://github.com/o1-labs/o1js/compare/1ad7333e9e...5495399cc) - 2024-12-10 +## [2.2.0](https://github.com/o1-labs/o1js/compare/e1bac02...b857516) - 2024-12-10 ### Added From bab0ce17b3efd18ef7052e52bc6f02d721801e6e Mon Sep 17 00:00:00 2001 From: Florian Date: Tue, 10 Dec 2024 19:35:45 +0700 Subject: [PATCH 288/328] point to correct PR --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8cbaa37616..3dd4c5c943 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -65,7 +65,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - `divMod64()` division modulo 2^64 that returns the remainder and quotient of the operation - `addMod64()` addition modulo 2^64 - Bitwise OR via `{UInt32, UInt64}.or()` -- **BLAKE2B hash function** gadget [#1285](https://github.com/o1-labs/o1js/pull/1285) +- **BLAKE2B hash function** gadget. https://github.com/o1-labs/o1js/pull/1767 ## [1.9.1](https://github.com/o1-labs/o1js/compare/f15293a69...7e9394) - 2024-10-15 From 7fdae2a423e090cb660f08b5aa0b1e76885dda6e Mon Sep 17 00:00:00 2001 From: Coby Date: Wed, 11 Dec 2024 09:53:54 -0500 Subject: [PATCH 289/328] Configure GH before creating a tag --- .github/workflows/build-action.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/build-action.yml b/.github/workflows/build-action.yml index 1a540c97bd..b3edeefeb9 100644 --- a/.github/workflows/build-action.yml +++ b/.github/workflows/build-action.yml @@ -311,6 +311,11 @@ jobs: env: INPUT_TOKEN: ${{ secrets.NPM_TOKEN }} + - name: Configure Git + run: | + git config --local user.email "action@github.com" + git config --local user.name "GitHub Action" + - name: Tag new version if: ${{ steps.publish.outputs.type }} # https://github.com/JS-DevTools/npm-publish?tab=readme-ov-file#action-output env: From 6e62e5d9ef181a6c0eae512dd61e1f88a7792e3d Mon Sep 17 00:00:00 2001 From: Geometer1729 <16kuhnb@gmail.com> Date: Wed, 11 Dec 2024 10:14:46 -0500 Subject: [PATCH 290/328] fix permision issue --- flake.nix | 1 + src/bindings | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index cce269049a..06126b807f 100644 --- a/flake.nix +++ b/flake.nix @@ -284,6 +284,7 @@ text = '' cp -r ${self.packages."${system}".o1js-bindings}/* ./src/bindings + chmod +w -R src/bindings/compiled MINA_COMMIT=$(git -C src/mina rev-parse HEAD) echo "The mina commit used to generate the backends for node and web is" "$MINA_COMMIT" \ > src/bindings/MINA_COMMIT diff --git a/src/bindings b/src/bindings index 181985212c..a5a0883f03 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit 181985212cd11d0f514a64f83d88490103e63d07 +Subproject commit a5a0883f033afd4c9fd4bf96a5e0b8ebd92a87c9 From 504c22263e90f61cf0ae389a13644a827fc71960 Mon Sep 17 00:00:00 2001 From: Geometer1729 <16kuhnb@gmail.com> Date: Wed, 11 Dec 2024 10:32:13 -0500 Subject: [PATCH 291/328] update npmDepsHash --- flake.nix | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/flake.nix b/flake.nix index 06126b807f..06b2172fec 100644 --- a/flake.nix +++ b/flake.nix @@ -158,6 +158,15 @@ ./package-lock.json ]; }); + # If you see 'ERROR: npmDepsHash is out of date' in ci + # set this to blank run ``nix build o1js#o1js-bindings` You should get an output like this: + # If you don't want to install nix you can also set it to "" and run ci to get the new hash + + # error: hash mismatch in fixed-output derivation '/nix/store/a03cg2az0b2cvjsp1wnr89clf31i79c1-o1js-npm-deps.drv': + # specified: sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= + # got: sha256-8EPvXpOgn0nvm/pFKN3h6EMjabOeBqfy5optIfe8E8Q= + # replace npmDepsHash bellow with the new hash + npmDepsHash = "sha256-8EPvXpOgn0nvm/pFKN3h6EMjabOeBqfy5optIfe8E8Q="; # The prepack script runs the build script, which we'd rather do in the build phase. npmPackFlags = [ "--ignore-scripts" ]; From 4e3fc935e6c8ca1797b58ae8cbdd412145f31efc Mon Sep 17 00:00:00 2001 From: Geometer1729 <16kuhnb@gmail.com> Date: Wed, 11 Dec 2024 10:56:08 -0500 Subject: [PATCH 292/328] update npmDepsHash again --- flake.nix | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/flake.nix b/flake.nix index 06b2172fec..cdca7f76a7 100644 --- a/flake.nix +++ b/flake.nix @@ -159,15 +159,16 @@ ]; }); # If you see 'ERROR: npmDepsHash is out of date' in ci - # set this to blank run ``nix build o1js#o1js-bindings` You should get an output like this: + # set this to blank run ``nix build o1js#o1js-bindings` # If you don't want to install nix you can also set it to "" and run ci to get the new hash + # You should get an output like this: # error: hash mismatch in fixed-output derivation '/nix/store/a03cg2az0b2cvjsp1wnr89clf31i79c1-o1js-npm-deps.drv': # specified: sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= # got: sha256-8EPvXpOgn0nvm/pFKN3h6EMjabOeBqfy5optIfe8E8Q= # replace npmDepsHash bellow with the new hash - npmDepsHash = "sha256-8EPvXpOgn0nvm/pFKN3h6EMjabOeBqfy5optIfe8E8Q="; + npmDepsHash = "sha256-QLnSfX6JwYQXyHGNSxXdzqbhkbFl67sDrmlW/F6D/pw="; # The prepack script runs the build script, which we'd rather do in the build phase. npmPackFlags = [ "--ignore-scripts" ]; dontNpmBuild = true; From 8218d130fa6183991eefda0bddd15be7f5ccb86f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ana=C3=AFs=20Querol?= Date: Thu, 12 Dec 2024 12:04:45 +0000 Subject: [PATCH 293/328] update with Brian's comments about storage handling and runtime optimmization --- README-nix.md | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/README-nix.md b/README-nix.md index f47241f6dc..b9ad6c1ef5 100644 --- a/README-nix.md +++ b/README-nix.md @@ -89,7 +89,7 @@ alternatively `nix develop o1js#mina-shell` (which works better from MacOS). nix develop o1js#default ``` -You will observe that the current devshell becomes a Nix shell with the right +The first time you run this command, you can expect it to take hours (or even a full day) to complete. Then, you will observe that the current devshell becomes a Nix shell with the right configuration for `o1js` and `mina`. In order to make sure that the bindings will be regenerated in the case that you @@ -123,6 +123,35 @@ cd ./src/mina nix develop mina ``` +## Desirable configurations + +### Storage handling + +Using Nix can take up a lot of disk space if not optimized. Every time you run `nix develop {SOMETHING}`, Nix will create new generations taking gigabytes of data instead of replacing the old ones. This can soon become a problem in your hard disk if you don't handle it carefully. Here are a few indications that can help with this. + +Nix has a garbage collector that **is not used by default** after every run. Instead, artifacts get accumulated in your disk unless configured otherwise. But if the full gargabe collector is executed (`nix-store --gc`), it will get the dependencies removed completely, and you can expect that the next time executing the Nix build will take hours to complete. + +Instead, you can try to run `nix-env --delete-generations old` or any other time bound like `7d`. This will not have any effect on MacOS though. Alternatively, the [direnv](https://github.com/direnv/direnv) / [nix-direnv](https://github.com/nix-community/nix-direnv) tool can create garbage collector roots that won't be collected for removal. It just keeps one gc-root to the latest build of the dev shell so that `nix-store --gc` only removes older generations. + +On top of that, adding `auto-optimise-store = true` to `/etc/nix/nix.conf` and running `nix-store --optimize` shoud help with disk usage, as it replaces duplicated files with symlinks. + +### Runtime optimization + +Other configurations are worth adding into your `/etc/nix/nix.conf`: + +```bash +keep-otuputs = true +max-jobs = 20 +extra-substituters = https://storage.googleapis.com/mina-nix-cache +extra-trusted-public-keys = nix-cache.minaprotocol.org:fdcuDzmnM0Kbf7yU4yywBuUEJWClySc1WIF6t6Mm8h4= nix-cache.minaprotocol.org:D3B1W+V7ND1Fmfii8EhbAbF1JXoe2Ct4N34OKChwk2c= mina-nix-cache-1:djtioLfv2oxuK2lqPUgmZbf8bY8sK/BnYZCU2iU5Q10= +``` + +The first of those flags tells the garbage collector to keep build time dependencies of current gc-roots, which should help reduce the amount of data that gets removed and rebuilt. + +The second flag increases the default number of jobs being 1, so that rebuilding from scratch will take shorter time. + +The last two lines tell Nix to use the Mina Foundation's cache whenever possible, which should as well speed things up when building code that has been build in Mina's CI before. + ## Common errors Errors while using Nix have been reported. This section collects a set of common @@ -268,4 +297,4 @@ Then, the error message would still contain old directories. #### Fix -Create a new environment for Nix and start from scratch. +Create a new environment for Nix and start from scratch. In particular, run the garbage collector which will remove old dependencies. From 2b115de9bce125915b3fce8ee3409c8af12f194d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ana=C3=AFs=20Querol?= Date: Thu, 12 Dec 2024 12:14:12 +0000 Subject: [PATCH 294/328] add disclaimer about error fixes --- README-nix.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README-nix.md b/README-nix.md index b9ad6c1ef5..6ff38494cd 100644 --- a/README-nix.md +++ b/README-nix.md @@ -157,6 +157,14 @@ The last two lines tell Nix to use the Mina Foundation's cache whenever possible Errors while using Nix have been reported. This section collects a set of common errors and proposes fixes for them. +```console +DISCLAIMER! + +The proposed solutions might not work universally, and could vary depending on your local environment. +This section should be read as a starting roadmap, and engineers are highly encouraged to add any new error found +and possible fixes to improve the helpfulness of this document. +``` + ### Compiling _export_test_vectors_ When trying to update the bindings for o1js in MacOS, Nix might fail at From 20690d1390e510f290f05871ad07575688df1d7a Mon Sep 17 00:00:00 2001 From: Geometer1729 <16kuhnb@gmail.com> Date: Thu, 12 Dec 2024 13:28:38 -0500 Subject: [PATCH 295/328] address Matt's review --- .github/workflows/build-bindings.yml | 1 - flake.nix | 5 ++--- pin.sh | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build-bindings.yml b/.github/workflows/build-bindings.yml index f5d92f8385..38e8f821e7 100644 --- a/.github/workflows/build-bindings.yml +++ b/.github/workflows/build-bindings.yml @@ -32,7 +32,6 @@ jobs: cd src/bindings git diff --exit-code - name: add build to gc-root if on main - # enabeling on this branch for 1 commit to test it if: github.ref == 'refs/heads/main' run: | nix build o1js#o1js-bindings --out-link /home/app/actions-runner/nix-cache/main-bindings-gcroot diff --git a/flake.nix b/flake.nix index cdca7f76a7..74f10868af 100644 --- a/flake.nix +++ b/flake.nix @@ -104,10 +104,10 @@ '' if [ "$1" = run ] && { [ "$2" = nightly-2023-09-01 ] || [ "$2" = 1.72-x86_64-unknowl-linux-gnu ]; } then - echo USING NIX TOOLCHAIN + echo using nix toolchain ${rustup}/bin/rustup run nix "''${@:3}" else - echo escape rustup "$@" + echo using plain rustup "$@" ${rustup}/bin/rustup "$@" fi ''; @@ -184,7 +184,6 @@ test-vectors = rust-platform.buildRustPackage { src = pkgs.lib.sourceByRegex ./src/mina/src [ - "^lib(/crypto(/kimchi_bindings(/stubs(/.*)?)?)?)?$" "^lib(/crypto(/proof-systems(/.*)?)?)?$" ]; sourceRoot = "source/lib/crypto/proof-systems/poseidon/export_test_vectors"; diff --git a/pin.sh b/pin.sh index e56e8e4425..4007b0d180 100755 --- a/pin.sh +++ b/pin.sh @@ -9,6 +9,6 @@ git submodule sync && git submodule update --init --recursive # Add the flake registry entry nix registry add o1js "git+file://$ROOT?submodules=1" # update mina input to local submodule -# --override-input seems redundant but fixes a cacheing issue with local paths +# --override-input seems redundant but fixes a caching issue with local paths nix flake update mina --override-input mina 'path:src/mina' --flake '.?submodules=1' popd From 422f6227196b8054f9ccf1b05e7d8af0b7af647e Mon Sep 17 00:00:00 2001 From: futreall <86553580+futreall@users.noreply.github.com> Date: Sat, 14 Dec 2024 23:41:18 +0200 Subject: [PATCH 296/328] Update account-update.ts --- src/lib/mina/account-update.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/mina/account-update.ts b/src/lib/mina/account-update.ts index 83ad585372..8bfcd71d60 100644 --- a/src/lib/mina/account-update.ts +++ b/src/lib/mina/account-update.ts @@ -552,7 +552,7 @@ interface Body extends AccountUpdateBody { * Events can be collected by archive nodes. * * [Check out our documentation about - * Events!](https://docs.minaprotocol.com/zkapps/advanced-o1js/events) + * Events!](https://docs.minaprotocol.com/zkapps/writing-a-zkapp/feature-overview/events) */ events: Events; /** @@ -561,7 +561,7 @@ interface Body extends AccountUpdateBody { * a {@link Reducer}. * * [Check out our documentation about - * Actions!](https://docs.minaprotocol.com/zkapps/advanced-o1js/actions-and-reducer) + * Actions!](https://docs.minaprotocol.com/zkapps/writing-a-zkapp/feature-overview/actions-and-reducer) */ actions: Events; /** From 79f1fd18f93d9c9643b89f89cbc91211583ae50f Mon Sep 17 00:00:00 2001 From: hattyhattington17 <181872047+hattyhattington17@users.noreply.github.com> Date: Sun, 15 Dec 2024 19:35:26 -0700 Subject: [PATCH 297/328] rebuild bindings --- src/bindings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bindings b/src/bindings index 317c73252b..0c908a2c1d 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit 317c73252b85702570ca95e85943cf749727074c +Subproject commit 0c908a2c1dd2c9c444a2f65aaf52dcdcc616a4b5 From 92dd1a34df1381e31ba1a094125c9f6225a6ddf4 Mon Sep 17 00:00:00 2001 From: hattyhattington17 <181872047+hattyhattington17@users.noreply.github.com> Date: Sun, 15 Dec 2024 19:53:39 -0700 Subject: [PATCH 298/328] remove duplicate test vectors in mina signer --- src/mina-signer/src/sign-legacy.unit-test.ts | 4 +- .../src/test-vectors/legacySignatures.ts | 56 ------------------- 2 files changed, 3 insertions(+), 57 deletions(-) diff --git a/src/mina-signer/src/sign-legacy.unit-test.ts b/src/mina-signer/src/sign-legacy.unit-test.ts index 2a54a56cf2..30cf195743 100644 --- a/src/mina-signer/src/sign-legacy.unit-test.ts +++ b/src/mina-signer/src/sign-legacy.unit-test.ts @@ -29,7 +29,9 @@ let networks: NetworkId[] = ['devnet', 'testnet', 'mainnet']; for (let network of networks) { let i = 0; - let reference = signatures[NetworkId.toString(network)]; + let reference = NetworkId.toString(network) === 'testnet' + ? signatures['devnet'] + : signatures[NetworkId.toString(network)]; for (let payment of payments) { let signature = signPayment(payment, privateKey, network); diff --git a/src/mina-signer/src/test-vectors/legacySignatures.ts b/src/mina-signer/src/test-vectors/legacySignatures.ts index db17f153e9..7cb559ce6d 100644 --- a/src/mina-signer/src/test-vectors/legacySignatures.ts +++ b/src/mina-signer/src/test-vectors/legacySignatures.ts @@ -147,62 +147,6 @@ let signatures: { [k: string]: { field: string; scalar: string }[] } = { '21219917886278462345652813021708727397787183083051040637716760620250038837684', }, ], - testnet: [ - { - field: - '3925887987173883783388058255268083382298769764463609405200521482763932632383', - scalar: - '445615701481226398197189554290689546503290167815530435382795701939759548136', - }, - { - field: - '11838925242791061185900891854974280922359055483441419242429642295065318643984', - scalar: - '5057044820006008308046028014628135487302791372585541488835641418654652928805', - }, - { - field: - '13570419670106759824217358880396743605262660069048455950202130815805728575057', - scalar: - '2256128221267944805514947515637443480133552241968312777663034361688965989223', - }, - { - field: - '18603328765572408555868399359399411973012220541556204196884026585115374044583', - scalar: - '17076342019359061119005549736934690084415105419939473687106079907606137611470', - }, - { - field: - '1786373894608285187089973929748850875336413409295396991315429715474432640801', - scalar: - '10435258496141097615588833319454104720521911644724923418749752896069542389757', - }, - { - field: - '11710586766419351067338319607483640291676872446372400739329190129174446858072', - scalar: - '21663533922934564101122062377096487451020504743791218020915919810997397884837', - }, - { - field: - '11583775536286847540414661987230057163492736306749717851628536966882998258109', - scalar: - '14787360096063782022566783796923142259879388947509616216546009448340181956495', - }, - { - field: - '24809097509137086694730479515383937245108109696879845335879579016397403384488', - scalar: - '23723859937408726087117568974923795978435877847592289069941156359435022279156', - }, - { - field: - '23803497755408154859878117448681790665144834176143832235351783889976460433296', - scalar: - '21219917886278462345652813021708727397787183083051040637716760620250038837684', - }, - ], mainnet: [ { field: From 67bdf864e0417022d2616ee44f098a1b46a5f958 Mon Sep 17 00:00:00 2001 From: Gregor Date: Tue, 17 Dec 2024 16:09:37 +0100 Subject: [PATCH 299/328] remove recursive provers and expose regular provers instead --- src/lib/proof-system/zkprogram.ts | 100 +++++++++--------------------- 1 file changed, 30 insertions(+), 70 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 5bff2a05fa..ad567024da 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -80,6 +80,9 @@ export { Prover, dummyBase64Proof, computeMaxProofsVerified, + RegularProver, + TupleToInstances, + PrivateInput, }; type Undefined = undefined; @@ -202,9 +205,9 @@ function ZkProgram< // derived types for convenience MethodSignatures extends Config['methods'] = Config['methods'], PrivateInputs extends { - [I in keyof MethodSignatures]: MethodSignatures[I]['privateInputs']; + [I in keyof Config['methods']]: Config['methods'][I]['privateInputs']; } = { - [I in keyof MethodSignatures]: MethodSignatures[I]['privateInputs']; + [I in keyof Config['methods']]: Config['methods'][I]['privateInputs']; }, AuxiliaryOutputs extends { [I in keyof MethodSignatures]: Get; @@ -247,11 +250,12 @@ function ZkProgram< rawMethods: { [I in keyof Config['methods']]: Methods[I]['method']; }; - proveRecursively: { - [I in keyof Config['methods']]: RecursiveProver< + provers: { + [I in keyof Config['methods']]: RegularProver< InferProvableOrUndefined>, InferProvableOrVoid>, - PrivateInputs[I] + PrivateInputs[I], + InferProvableOrUndefined >; }; proofsEnabled: boolean; @@ -379,18 +383,17 @@ function ZkProgram< // for each of the methods, create a prover function. // in the first step, these are "regular" in that they always expect the public input as the first argument, // which is easier to use internally. - type RegularProver = ( - publicInput: PublicInput, - ...args: PrivateInputs[K] - ) => Promise<{ - proof: Proof; - auxiliaryOutput: InferProvableOrUndefined; - }>; + type RegularProver_ = RegularProver< + PublicInput, + PublicOutput, + PrivateInputs[K], + InferProvableOrUndefined + >; function toRegularProver( key: K, i: number - ): RegularProver { + ): RegularProver_ { return async function prove_(publicInput, ...args) { if (!doProving) { // we step into a ZkProgramContext here to match the context nesting @@ -516,50 +519,6 @@ function ZkProgram< return compileOutput.verify(statement, proof.proof); } - let regularRecursiveProvers = mapObject(regularProvers, (prover, key) => { - return async function proveRecursively_( - publicInput: PublicInput, - ...args: TupleToInstances - ) { - // create the base proof in a witness block - let proof = await Provable.witnessAsync(SelfProof, async () => { - // move method args to constants - let constInput = Provable.toConstant(publicInputType, publicInput); - let constArgs = zip(args, methods[key].privateInputs).map( - ([arg, type]) => Provable.toConstant(type, arg) - ); - let { proof } = await prover(constInput, ...(constArgs as any)); - return proof; - }); - - // assert that the witnessed proof has the correct public input (which will be used by Pickles as part of verification) - if (hasPublicInput) { - Provable.assertEqual(publicInputType, proof.publicInput, publicInput); - } - - // declare and verify the proof, and return its public output - proof.declare(); - proof.verify(); - return proof.publicOutput; - }; - }); - type RecursiveProver_ = RecursiveProver< - PublicInput, - PublicOutput, - PrivateInputs[K] - >; - type RecursiveProvers = { - [K in MethodKey]: RecursiveProver_; - }; - let proveRecursively: RecursiveProvers = mapToObject(methodKeys, (key) => { - if (publicInputType === Undefined || publicInputType === Void) { - return ((...args: any) => - regularRecursiveProvers[key](undefined as any, ...args)) as any; - } else { - return regularRecursiveProvers[key] as any; - } - }); - async function digest() { let methodsMeta = await analyzeMethods(); let digests: Field[] = methodKeys.map((k) => @@ -590,12 +549,11 @@ function ZkProgram< rawMethods: Object.fromEntries( methodKeys.map((key) => [key, methods[key].method]) ) as any, + provers: regularProvers, proofsEnabled: doProving, setProofsEnabled(proofsEnabled: boolean) { doProving = proofsEnabled; }, - - proveRecursively, }, provers ); @@ -1227,6 +1185,19 @@ type Method< >; }; +type RegularProver< + PublicInput, + PublicOutput, + Args extends Tuple, + AuxiliaryOutput +> = ( + publicInput: PublicInput, + ...args: TupleToInstances +) => Promise<{ + proof: Proof; + auxiliaryOutput: AuxiliaryOutput; +}>; + type Prover< PublicInput, PublicOutput, @@ -1245,17 +1216,6 @@ type Prover< auxiliaryOutput: AuxiliaryOutput; }>; -type RecursiveProver< - PublicInput, - PublicOutput, - Args extends Tuple -> = PublicInput extends undefined - ? (...args: TupleToInstances) => Promise - : ( - publicInput: PublicInput, - ...args: TupleToInstances - ) => Promise; - type ProvableOrUndefined = A extends undefined ? typeof Undefined : ToProvable; From 484ff136cc2697fd9a1548e15a19a0be2183890c Mon Sep 17 00:00:00 2001 From: Gregor Date: Tue, 17 Dec 2024 16:09:51 +0100 Subject: [PATCH 300/328] recursive provers in separate wapper --- src/lib/proof-system/recursive.ts | 132 ++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 src/lib/proof-system/recursive.ts diff --git a/src/lib/proof-system/recursive.ts b/src/lib/proof-system/recursive.ts new file mode 100644 index 0000000000..6a9306943a --- /dev/null +++ b/src/lib/proof-system/recursive.ts @@ -0,0 +1,132 @@ +import { InferProvable } from '../provable/types/struct.js'; +import { Provable } from '../provable/provable.js'; +import { ProvableType } from '../provable/types/provable-intf.js'; +import { Tuple } from '../util/types.js'; +import { Proof } from './proof.js'; +import { mapObject, mapToObject, zip } from '../util/arrays.js'; +import { RegularProver, Undefined, Void } from './zkprogram.js'; + +export { Recursive }; + +function Recursive< + PublicInputType extends Provable, + PublicOutputType extends Provable, + PrivateInputs extends { + [Key in string]: Tuple; + } +>(zkprogram: { + name: string; + publicInputType: PublicInputType; + publicOutputType: PublicOutputType; + privateInputTypes: PrivateInputs; + rawMethods: { + [Key in keyof PrivateInputs]: ( + ...args: any + ) => Promise<{ publicOutput: InferProvable }>; + }; + provers: { + [Key in keyof PrivateInputs]: RegularProver< + InferProvable, + InferProvable, + any, + any + >; + }; +}): { + [Key in keyof PrivateInputs]: RecursiveProver< + InferProvable, + InferProvable, + PrivateInputs[Key] + >; +} { + type PublicInput = InferProvable; + type PublicOutput = InferProvable; + type MethodKey = keyof PrivateInputs; + + let { + publicInputType, + publicOutputType, + privateInputTypes: privateInputs, + rawMethods: methods, + provers, + } = zkprogram; + + let hasPublicInput = + publicInputType !== Undefined && publicInputType !== Void; + + class SelfProof extends Proof { + static publicInputType = publicInputType; + static publicOutputType = publicOutputType; + static tag = () => zkprogram; + } + + let methodKeys: MethodKey[] = Object.keys(methods); + + let regularRecursiveProvers = mapObject(provers, (prover, key) => { + return async function proveRecursively_( + publicInput: PublicInput, + ...args: TupleToInstances + ) { + // create the base proof in a witness block + let proof = await Provable.witnessAsync(SelfProof, async () => { + // move method args to constants + let constInput = Provable.toConstant( + publicInputType, + publicInput + ); + let constArgs = zip(args, privateInputs[key]).map(([arg, type]) => + Provable.toConstant(type, arg) + ); + let { proof } = await prover(constInput, ...(constArgs as any)); + return proof; + }); + + // assert that the witnessed proof has the correct public input (which will be used by Pickles as part of verification) + if (hasPublicInput) { + Provable.assertEqual(publicInputType, proof.publicInput, publicInput); + } + + // declare and verify the proof, and return its public output + proof.declare(); + proof.verify(); + return proof.publicOutput; + }; + }); + + type RecursiveProver_ = RecursiveProver< + PublicInput, + PublicOutput, + PrivateInputs[K] + >; + type RecursiveProvers = { + [K in MethodKey]: RecursiveProver_; + }; + let proveRecursively: RecursiveProvers = mapToObject( + methodKeys, + (key: MethodKey) => { + if (!hasPublicInput) { + return ((...args: any) => + regularRecursiveProvers[key](undefined as any, ...args)) as any; + } else { + return regularRecursiveProvers[key] as any; + } + } + ); + + return proveRecursively; +} + +type RecursiveProver< + PublicInput, + PublicOutput, + Args extends Tuple +> = PublicInput extends undefined + ? (...args: TupleToInstances) => Promise + : ( + publicInput: PublicInput, + ...args: TupleToInstances + ) => Promise; + +type TupleToInstances = { + [I in keyof T]: InferProvable; +}; From b1adf8e946c3c775098f759efae1748fdd3ac66a Mon Sep 17 00:00:00 2001 From: Gregor Date: Tue, 17 Dec 2024 16:09:58 +0100 Subject: [PATCH 301/328] export Recursive --- src/index.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/index.ts b/src/index.ts index 1d27d3a869..a2dc54d686 100644 --- a/src/index.ts +++ b/src/index.ts @@ -148,6 +148,7 @@ import * as OffchainState_ from './lib/mina/actions/offchain-state.js'; import * as BatchReducer_ from './lib/mina/actions/batch-reducer.js'; import { Actionable } from './lib/mina/actions/offchain-state-serialization.js'; import { InferProvable } from './lib/provable/types/struct.js'; +import { Recursive as Recursive_ } from './lib/proof-system/recursive.js'; export { Experimental }; const Experimental_ = { @@ -162,6 +163,8 @@ const Experimental_ = { namespace Experimental { export let memoizeWitness = Experimental_.memoizeWitness; + export let Recursive = Recursive_; + // indexed merkle map export let IndexedMerkleMap = Experimental_.IndexedMerkleMap; export type IndexedMerkleMap = IndexedMerkleMapBase; From d0ffd756267efff255804a008cc9fc0893a72172 Mon Sep 17 00:00:00 2001 From: Gregor Date: Tue, 17 Dec 2024 16:10:04 +0100 Subject: [PATCH 302/328] adapt changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f7d4b29a25..113e054197 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,7 +23,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - `ZkProgram` to support non-pure provable types as inputs and outputs https://github.com/o1-labs/o1js/pull/1828 - API for recursively proving a ZkProgram method from within another https://github.com/o1-labs/o1js/pull/1931 - - `program.proveRecursively.(...args): Promise` + - `let recursive = Experimental.Recursive(program); recursive.(...args): Promise` - This also works within the same program, as long as the return value is type-annotated - Add `enforceTransactionLimits` parameter on Network https://github.com/o1-labs/o1js/issues/1910 - Method for optional types to assert none https://github.com/o1-labs/o1js/pull/1922 From 353f639f7bd00f8c4728399d2901a5c173044524 Mon Sep 17 00:00:00 2001 From: Gregor Date: Tue, 17 Dec 2024 16:18:11 +0100 Subject: [PATCH 303/328] remove the need to export regular provers --- src/lib/proof-system/recursive.ts | 53 +++++++++++++++++-------------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/src/lib/proof-system/recursive.ts b/src/lib/proof-system/recursive.ts index 6a9306943a..23dbd41860 100644 --- a/src/lib/proof-system/recursive.ts +++ b/src/lib/proof-system/recursive.ts @@ -4,7 +4,7 @@ import { ProvableType } from '../provable/types/provable-intf.js'; import { Tuple } from '../util/types.js'; import { Proof } from './proof.js'; import { mapObject, mapToObject, zip } from '../util/arrays.js'; -import { RegularProver, Undefined, Void } from './zkprogram.js'; +import { Undefined, Void } from './zkprogram.js'; export { Recursive }; @@ -14,25 +14,26 @@ function Recursive< PrivateInputs extends { [Key in string]: Tuple; } ->(zkprogram: { - name: string; - publicInputType: PublicInputType; - publicOutputType: PublicOutputType; - privateInputTypes: PrivateInputs; - rawMethods: { - [Key in keyof PrivateInputs]: ( - ...args: any - ) => Promise<{ publicOutput: InferProvable }>; - }; - provers: { - [Key in keyof PrivateInputs]: RegularProver< - InferProvable, - InferProvable, - any, - any - >; - }; -}): { +>( + zkprogram: { + name: string; + publicInputType: PublicInputType; + publicOutputType: PublicOutputType; + privateInputTypes: PrivateInputs; + rawMethods: { + [Key in keyof PrivateInputs]: ( + ...args: any + ) => Promise<{ publicOutput: InferProvable }>; + }; + } & { + [Key in keyof PrivateInputs]: (...args: any) => Promise<{ + proof: Proof< + InferProvable, + InferProvable + >; + }>; + } +): { [Key in keyof PrivateInputs]: RecursiveProver< InferProvable, InferProvable, @@ -48,7 +49,6 @@ function Recursive< publicOutputType, privateInputTypes: privateInputs, rawMethods: methods, - provers, } = zkprogram; let hasPublicInput = @@ -62,7 +62,7 @@ function Recursive< let methodKeys: MethodKey[] = Object.keys(methods); - let regularRecursiveProvers = mapObject(provers, (prover, key) => { + let regularRecursiveProvers = mapObject(zkprogram, (prover, key) => { return async function proveRecursively_( publicInput: PublicInput, ...args: TupleToInstances @@ -77,8 +77,13 @@ function Recursive< let constArgs = zip(args, privateInputs[key]).map(([arg, type]) => Provable.toConstant(type, arg) ); - let { proof } = await prover(constInput, ...(constArgs as any)); - return proof; + if (hasPublicInput) { + let { proof } = await prover(constInput, ...constArgs); + return proof; + } else { + let { proof } = await prover(...constArgs); + return proof; + } }); // assert that the witnessed proof has the correct public input (which will be used by Pickles as part of verification) From 671685e6196a9e7ed6c097b3e4b78f68da01d34d Mon Sep 17 00:00:00 2001 From: Gregor Date: Tue, 17 Dec 2024 16:19:11 +0100 Subject: [PATCH 304/328] remove regular provers --- src/lib/proof-system/zkprogram.ts | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index ad567024da..9629f56cb7 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -250,14 +250,6 @@ function ZkProgram< rawMethods: { [I in keyof Config['methods']]: Methods[I]['method']; }; - provers: { - [I in keyof Config['methods']]: RegularProver< - InferProvableOrUndefined>, - InferProvableOrVoid>, - PrivateInputs[I], - InferProvableOrUndefined - >; - }; proofsEnabled: boolean; setProofsEnabled(proofsEnabled: boolean): void; } & { @@ -549,7 +541,6 @@ function ZkProgram< rawMethods: Object.fromEntries( methodKeys.map((key) => [key, methods[key].method]) ) as any, - provers: regularProvers, proofsEnabled: doProving, setProofsEnabled(proofsEnabled: boolean) { doProving = proofsEnabled; From 0d04ccc0c5e6e0e10bedf5ef1464f2bc24676635 Mon Sep 17 00:00:00 2001 From: Gregor Date: Tue, 17 Dec 2024 16:19:17 +0100 Subject: [PATCH 305/328] adapt example --- src/tests/inductive-proofs-internal.ts | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/tests/inductive-proofs-internal.ts b/src/tests/inductive-proofs-internal.ts index c2aefbf36d..0b1941f018 100644 --- a/src/tests/inductive-proofs-internal.ts +++ b/src/tests/inductive-proofs-internal.ts @@ -1,4 +1,4 @@ -import { Field, ZkProgram, assert, Provable, Proof } from 'o1js'; +import { Field, ZkProgram, assert, Provable, Proof, Experimental } from 'o1js'; import { tic, toc } from '../examples/utils/tic-toc.js'; let log: string[] = []; @@ -10,7 +10,7 @@ function pushLog(s: string) { }); } -let MaxProofsVerifiedTwo = ZkProgram({ +let mergeProgram = ZkProgram({ name: 'recursive-2', publicOutput: Field, @@ -31,7 +31,7 @@ let MaxProofsVerifiedTwo = ZkProgram({ async method() { pushLog('mergeOne'); let z = Provable.witness(Field, () => 0); - let x: Field = await MaxProofsVerifiedTwo.proveRecursively.baseCase(z); + let x: Field = await mergeProgramRecursive.baseCase(z); return { publicOutput: x.add(1) }; }, }, @@ -42,20 +42,21 @@ let MaxProofsVerifiedTwo = ZkProgram({ async method() { pushLog('mergeTwo'); let z = Provable.witness(Field, () => 0); - let x: Field = await MaxProofsVerifiedTwo.proveRecursively.baseCase(z); - let y: Field = await MaxProofsVerifiedTwo.proveRecursively.mergeOne(); + let x: Field = await mergeProgramRecursive.baseCase(z); + let y: Field = await mergeProgramRecursive.mergeOne(); return { publicOutput: x.add(y) }; }, }, }, }); +let mergeProgramRecursive = Experimental.Recursive(mergeProgram); let Wrapper = ZkProgram({ name: 'wraps-recursive-2', methods: { wrap: { - privateInputs: [ZkProgram.Proof(MaxProofsVerifiedTwo)], + privateInputs: [ZkProgram.Proof(mergeProgram)], async method(proof: Proof) { proof.verify(); @@ -67,15 +68,15 @@ let Wrapper = ZkProgram({ }); tic('compiling'); -await MaxProofsVerifiedTwo.compile(); +await mergeProgram.compile(); await Wrapper.compile(); toc(); tic('executing 4 proofs'); -let { proof } = await MaxProofsVerifiedTwo.mergeTwo(); +let { proof } = await mergeProgram.mergeTwo(); toc(); -assert(await MaxProofsVerifiedTwo.verify(proof), 'Proof is not valid'); +assert(await mergeProgram.verify(proof), 'Proof is not valid'); proof.publicOutput.assertEquals(15); From c36b64ad57f1d3ffa394cc9b80242ec9b0fc47de Mon Sep 17 00:00:00 2001 From: Gregor Date: Tue, 17 Dec 2024 16:28:02 +0100 Subject: [PATCH 306/328] merge fixup --- src/lib/proof-system/zkprogram.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 20014c6298..b6e39ee960 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -553,7 +553,6 @@ function ZkProgram< rawMethods: Object.fromEntries( methodKeys.map((key) => [key, methods[key].method]) ) as any, - proveRecursively, Proof: SelfProof, From e59b340bba83c5b14cad76a9fbce06522e2651a0 Mon Sep 17 00:00:00 2001 From: Gregor Date: Tue, 17 Dec 2024 16:29:13 +0100 Subject: [PATCH 307/328] changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 113e054197..392dc5c9e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,11 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Method for optional types to assert none https://github.com/o1-labs/o1js/pull/1922 - Increased maximum supported amount of methods in a `SmartContract` or `ZkProgram` to 30. https://github.com/o1-labs/o1js/pull/1918 - Expose low-level conversion methods `Proof.{_proofToBase64,_proofFromBase64}` https://github.com/o1-labs/o1js/pull/1928 +- Expore `maxProofsVerified()` and a `Proof` class directly on ZkPrograms https://github.com/o1-labs/o1js/pull/1933 + +### Changed + +- Changed an internal type to improve IntelliSense on ZkProgram methods https://github.com/o1-labs/o1js/pull/1933 ### Fixed From 1a903d0b610ac94f8c08a46455cf8234b00f4952 Mon Sep 17 00:00:00 2001 From: Gregor Date: Tue, 17 Dec 2024 17:04:27 +0100 Subject: [PATCH 308/328] add back recursive conditional provers --- src/lib/proof-system/recursive.ts | 102 ++++++++++++++++++++++++------ 1 file changed, 82 insertions(+), 20 deletions(-) diff --git a/src/lib/proof-system/recursive.ts b/src/lib/proof-system/recursive.ts index 23dbd41860..d23ae101ab 100644 --- a/src/lib/proof-system/recursive.ts +++ b/src/lib/proof-system/recursive.ts @@ -5,6 +5,7 @@ import { Tuple } from '../util/types.js'; import { Proof } from './proof.js'; import { mapObject, mapToObject, zip } from '../util/arrays.js'; import { Undefined, Void } from './zkprogram.js'; +import { Bool } from '../provable/bool.js'; export { Recursive }; @@ -38,7 +39,13 @@ function Recursive< InferProvable, InferProvable, PrivateInputs[Key] - >; + > & { + if: ConditionalRecursiveProver< + InferProvable, + InferProvable, + PrivateInputs[Key] + >; + }; } { type PublicInput = InferProvable; type PublicOutput = InferProvable; @@ -62,11 +69,17 @@ function Recursive< let methodKeys: MethodKey[] = Object.keys(methods); - let regularRecursiveProvers = mapObject(zkprogram, (prover, key) => { + let regularRecursiveProvers = mapToObject(methodKeys, (key) => { return async function proveRecursively_( + conditionAndConfig: Bool | { condition: Bool; domainLog2?: number }, publicInput: PublicInput, ...args: TupleToInstances - ) { + ): Promise { + let condition = + conditionAndConfig instanceof Bool + ? conditionAndConfig + : conditionAndConfig.condition; + // create the base proof in a witness block let proof = await Provable.witnessAsync(SelfProof, async () => { // move method args to constants @@ -77,6 +90,24 @@ function Recursive< let constArgs = zip(args, privateInputs[key]).map(([arg, type]) => Provable.toConstant(type, arg) ); + + if (!condition.toBoolean()) { + let publicOutput: PublicOutput = + ProvableType.synthesize(publicOutputType); + let maxProofsVerified: 0 | 1 | 2 = + (await zkprogram.maxProofsVerified()) as any; // TODO + return SelfProof.dummy( + publicInput, + publicOutput, + maxProofsVerified, + conditionAndConfig instanceof Bool + ? undefined + : conditionAndConfig.domainLog2 + ); + } + + let prover = zkprogram[key]; + if (hasPublicInput) { let { proof } = await prover(constInput, ...constArgs); return proof; @@ -93,32 +124,48 @@ function Recursive< // declare and verify the proof, and return its public output proof.declare(); - proof.verify(); + proof.verifyIf(condition); return proof.publicOutput; }; }); - type RecursiveProver_ = RecursiveProver< - PublicInput, - PublicOutput, - PrivateInputs[K] - >; - type RecursiveProvers = { - [K in MethodKey]: RecursiveProver_; - }; - let proveRecursively: RecursiveProvers = mapToObject( - methodKeys, - (key: MethodKey) => { + return mapObject( + regularRecursiveProvers, + ( + prover + ): RecursiveProver & { + if: ConditionalRecursiveProver< + PublicInput, + PublicOutput, + PrivateInputs[MethodKey] + >; + } => { if (!hasPublicInput) { - return ((...args: any) => - regularRecursiveProvers[key](undefined as any, ...args)) as any; + return Object.assign( + ((...args: any) => + prover(new Bool(true), undefined as any, ...args)) as any, + { + if: ( + condition: Bool | { condition: Bool; domainLog2?: number }, + ...args: any + ) => prover(condition, undefined as any, ...args), + } + ); } else { - return regularRecursiveProvers[key] as any; + return Object.assign( + ((pi: PublicInput, ...args: any) => + prover(new Bool(true), pi, ...args)) as any, + { + if: ( + condition: Bool | { condition: Bool; domainLog2?: number }, + pi: PublicInput, + ...args: any + ) => prover(condition, pi, ...args), + } + ); } } ); - - return proveRecursively; } type RecursiveProver< @@ -132,6 +179,21 @@ type RecursiveProver< ...args: TupleToInstances ) => Promise; +type ConditionalRecursiveProver< + PublicInput, + PublicOutput, + Args extends Tuple +> = PublicInput extends undefined + ? ( + condition: Bool | { condition: Bool; domainLog2?: number }, + ...args: TupleToInstances + ) => Promise + : ( + condition: Bool | { condition: Bool; domainLog2?: number }, + publicInput: PublicInput, + ...args: TupleToInstances + ) => Promise; + type TupleToInstances = { [I in keyof T]: InferProvable; }; From bff1f194591142744a3c3cc6d55715d0974fcfaa Mon Sep 17 00:00:00 2001 From: Gregor Date: Tue, 17 Dec 2024 17:10:15 +0100 Subject: [PATCH 309/328] fix after merging other pr --- src/lib/proof-system/recursive.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/proof-system/recursive.ts b/src/lib/proof-system/recursive.ts index d23ae101ab..bdc6f10316 100644 --- a/src/lib/proof-system/recursive.ts +++ b/src/lib/proof-system/recursive.ts @@ -26,6 +26,7 @@ function Recursive< ...args: any ) => Promise<{ publicOutput: InferProvable }>; }; + maxProofsVerified: () => Promise<0 | 1 | 2>; } & { [Key in keyof PrivateInputs]: (...args: any) => Promise<{ proof: Proof< @@ -94,8 +95,7 @@ function Recursive< if (!condition.toBoolean()) { let publicOutput: PublicOutput = ProvableType.synthesize(publicOutputType); - let maxProofsVerified: 0 | 1 | 2 = - (await zkprogram.maxProofsVerified()) as any; // TODO + let maxProofsVerified = await zkprogram.maxProofsVerified(); return SelfProof.dummy( publicInput, publicOutput, From 6890754b2040c205e67a0898bdec3a306356aa83 Mon Sep 17 00:00:00 2001 From: Gregor Date: Tue, 17 Dec 2024 17:10:24 +0100 Subject: [PATCH 310/328] adapt hash chain example --- src/examples/zkprogram/hash-chain.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/examples/zkprogram/hash-chain.ts b/src/examples/zkprogram/hash-chain.ts index b009602e38..53bc574cf0 100644 --- a/src/examples/zkprogram/hash-chain.ts +++ b/src/examples/zkprogram/hash-chain.ts @@ -7,6 +7,7 @@ import { assert, Bool, + Experimental, Field, Poseidon, Provable, @@ -42,10 +43,10 @@ const hashChain = ZkProgram({ // we have y = hash^k(x) // now do z = hash^(n-k)(y) = hash^n(x) by calling this method recursively // except if we have k = n, then ignore the output and use y - let z: Field = await hashChain.proveRecursivelyIf.chain( - reachedN.not(), - { x: y, n: n.sub(k) } - ); + let z: Field = await hashChainRecursive.chain.if(reachedN.not(), { + x: y, + n: n.sub(k), + }); z = Provable.if(reachedN, y, z); Provable.log('hashChain (start proving)', n); return { publicOutput: z }; @@ -53,6 +54,7 @@ const hashChain = ZkProgram({ }, }, }); +let hashChainRecursive = Experimental.Recursive(hashChain); await hashChain.compile(); From c9c81f76db7e6774fddcf29635aa3d5b332d0a9d Mon Sep 17 00:00:00 2001 From: Gregor Date: Tue, 17 Dec 2024 17:13:24 +0100 Subject: [PATCH 311/328] changelog tweak --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 113e054197..0c0dc9b8d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,7 +23,8 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - `ZkProgram` to support non-pure provable types as inputs and outputs https://github.com/o1-labs/o1js/pull/1828 - API for recursively proving a ZkProgram method from within another https://github.com/o1-labs/o1js/pull/1931 - - `let recursive = Experimental.Recursive(program); recursive.(...args): Promise` + - `let recursive = Experimental.Recursive(program);` + - `recursive.(...args): Promise` - This also works within the same program, as long as the return value is type-annotated - Add `enforceTransactionLimits` parameter on Network https://github.com/o1-labs/o1js/issues/1910 - Method for optional types to assert none https://github.com/o1-labs/o1js/pull/1922 From bf1e275066b1fb6853fee41294e2b687d594d2e2 Mon Sep 17 00:00:00 2001 From: Gregor Date: Tue, 17 Dec 2024 17:16:22 +0100 Subject: [PATCH 312/328] final fix: avoid mapping over the entire zkprogram --- src/lib/proof-system/recursive.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/lib/proof-system/recursive.ts b/src/lib/proof-system/recursive.ts index 23dbd41860..f7f0a4a3f1 100644 --- a/src/lib/proof-system/recursive.ts +++ b/src/lib/proof-system/recursive.ts @@ -62,7 +62,7 @@ function Recursive< let methodKeys: MethodKey[] = Object.keys(methods); - let regularRecursiveProvers = mapObject(zkprogram, (prover, key) => { + let regularRecursiveProvers = mapToObject(methodKeys, (key) => { return async function proveRecursively_( publicInput: PublicInput, ...args: TupleToInstances @@ -77,6 +77,9 @@ function Recursive< let constArgs = zip(args, privateInputs[key]).map(([arg, type]) => Provable.toConstant(type, arg) ); + + let prover = zkprogram[key]; + if (hasPublicInput) { let { proof } = await prover(constInput, ...constArgs); return proof; From 3fdc3f1f42f0a838e832338f40194b40dc13981d Mon Sep 17 00:00:00 2001 From: querolita Date: Wed, 18 Dec 2024 13:36:34 +0100 Subject: [PATCH 313/328] update bindings without the huge diff --- src/bindings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bindings b/src/bindings index 317c73252b..e3a31e1e9c 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit 317c73252b85702570ca95e85943cf749727074c +Subproject commit e3a31e1e9cb136aae2509b4cfd1a03f84c1d443e From 1b6564d5d99f1285cbda0cd9f5edceb38fd40722 Mon Sep 17 00:00:00 2001 From: Geometer1729 <16kuhnb@gmail.com> Date: Wed, 18 Dec 2024 15:12:54 -0500 Subject: [PATCH 314/328] add action to upload a patch when bindings differ --- .github/workflows/build-bindings.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.github/workflows/build-bindings.yml b/.github/workflows/build-bindings.yml index 38e8f821e7..7fd7bf5391 100644 --- a/.github/workflows/build-bindings.yml +++ b/.github/workflows/build-bindings.yml @@ -39,3 +39,18 @@ jobs: run: | nix-store --gc --print-dead nix-store --optimise + patch-upload: + needs: nix-build + if: ${{ failure() }} + runs-on: [sdk-self-hosted-linux-amd64-build-system] + steps: + - name: generate patch + run: | + cd src/bindings + git add . + git diff HEAD > bindings.patch + - name: Upload patch + uses: actions/upload-artifact@v4 + with: + name: bindings.patch + path: src/bindings/bindings.patch From dacd84c3ae2d4f6ace913b15bacf54b018acc2fa Mon Sep 17 00:00:00 2001 From: Geometer1729 <16kuhnb@gmail.com> Date: Wed, 18 Dec 2024 15:22:03 -0500 Subject: [PATCH 315/328] add dummy file to bindings to test ci --- src/bindings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bindings b/src/bindings index a5a0883f03..59ba4b5e9d 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit a5a0883f033afd4c9fd4bf96a5e0b8ebd92a87c9 +Subproject commit 59ba4b5e9d74839d1655c21aca8582a0c68b4bdc From 6be1480d47f6d70cca731345af19529acd788618 Mon Sep 17 00:00:00 2001 From: Geometer1729 <16kuhnb@gmail.com> Date: Wed, 18 Dec 2024 15:36:12 -0500 Subject: [PATCH 316/328] bindings diff that will actually trip ci --- src/bindings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bindings b/src/bindings index 59ba4b5e9d..1e5c045095 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit 59ba4b5e9d74839d1655c21aca8582a0c68b4bdc +Subproject commit 1e5c0450950627341f14cf1ce5d7213f2bbd0565 From 9b04ffaa0cf0a0874e70cbe5fe2bb93e137a25cd Mon Sep 17 00:00:00 2001 From: Geometer1729 <16kuhnb@gmail.com> Date: Wed, 18 Dec 2024 15:39:25 -0500 Subject: [PATCH 317/328] fix bindings ref --- src/bindings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bindings b/src/bindings index 1e5c045095..74ac5f5e05 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit 1e5c0450950627341f14cf1ce5d7213f2bbd0565 +Subproject commit 74ac5f5e055b66a92cf88b6d9970d5103f1dbaaa From 7e99bba3538b072bfdcf8c5d4fe5d6c57a79a234 Mon Sep 17 00:00:00 2001 From: Geometer1729 <16kuhnb@gmail.com> Date: Wed, 18 Dec 2024 15:47:09 -0500 Subject: [PATCH 318/328] change path for patch and apply patch from github --- .github/workflows/build-bindings.yml | 4 ++-- src/bindings | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-bindings.yml b/.github/workflows/build-bindings.yml index 7fd7bf5391..5595c7df94 100644 --- a/.github/workflows/build-bindings.yml +++ b/.github/workflows/build-bindings.yml @@ -48,9 +48,9 @@ jobs: run: | cd src/bindings git add . - git diff HEAD > bindings.patch + git diff HEAD > ../../bindings.patch - name: Upload patch uses: actions/upload-artifact@v4 with: name: bindings.patch - path: src/bindings/bindings.patch + path: bindings.patch diff --git a/src/bindings b/src/bindings index 74ac5f5e05..58e02003f5 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit 74ac5f5e055b66a92cf88b6d9970d5103f1dbaaa +Subproject commit 58e02003f5a7889cf17025762ebfc81ac0d4b3d3 From 8fa9a0454815f9424c3593a46b1c17ce8a6b0db5 Mon Sep 17 00:00:00 2001 From: Geometer1729 <16kuhnb@gmail.com> Date: Wed, 18 Dec 2024 15:48:32 -0500 Subject: [PATCH 319/328] revert bindings to make sure new path works --- src/bindings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bindings b/src/bindings index 58e02003f5..74ac5f5e05 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit 58e02003f5a7889cf17025762ebfc81ac0d4b3d3 +Subproject commit 74ac5f5e055b66a92cf88b6d9970d5103f1dbaaa From d6e52c15259f2d60c96c211560b14eb30caabf26 Mon Sep 17 00:00:00 2001 From: Geometer1729 <16kuhnb@gmail.com> Date: Wed, 18 Dec 2024 15:52:09 -0500 Subject: [PATCH 320/328] restore bindings --- src/bindings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bindings b/src/bindings index 74ac5f5e05..58e02003f5 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit 74ac5f5e055b66a92cf88b6d9970d5103f1dbaaa +Subproject commit 58e02003f5a7889cf17025762ebfc81ac0d4b3d3 From 03595d4ff048fd479a06e4529096fd2e1ebffdbf Mon Sep 17 00:00:00 2001 From: Geometer1729 <16kuhnb@gmail.com> Date: Wed, 18 Dec 2024 15:59:41 -0500 Subject: [PATCH 321/328] just point bindings at main --- src/bindings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bindings b/src/bindings index 58e02003f5..f157000fad 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit 58e02003f5a7889cf17025762ebfc81ac0d4b3d3 +Subproject commit f157000fadd98f3699ed573ce7a3e3be784f6022 From 3d2854a84f576ae16bead9c4684fa4edb4fee484 Mon Sep 17 00:00:00 2001 From: Geometer1729 <16kuhnb@gmail.com> Date: Thu, 19 Dec 2024 09:23:56 -0500 Subject: [PATCH 322/328] add documentation for bindings patch (and break bindings) --- .github/workflows/build-bindings.yml | 2 ++ README-dev.md | 14 ++++++++++++++ src/bindings | 2 +- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-bindings.yml b/.github/workflows/build-bindings.yml index 5595c7df94..4a42d71a0b 100644 --- a/.github/workflows/build-bindings.yml +++ b/.github/workflows/build-bindings.yml @@ -30,6 +30,8 @@ jobs: nix run o1js#update-bindings --max-jobs 4 #fail if this changes any files cd src/bindings + echo If this check fails you can download a patch from the patch-upload job + echo "https://github.com/o1-labs/o1js/blob/main/README-dev.md#build-scripts" git diff --exit-code - name: add build to gc-root if on main if: github.ref == 'refs/heads/main' diff --git a/README-dev.md b/README-dev.md index 8d1ec0fbbc..6a7e08107f 100644 --- a/README-dev.md +++ b/README-dev.md @@ -86,6 +86,20 @@ In addition to building the OCaml and Rust code, the build script also generates o1js uses these types to ensure that the constants used in the protocol are consistent with the OCaml source files. +### Bindings check in ci + +If the bindings check fails in CI it will upload a patch you can use to update the bindings without having to rebuild locally. +This can also be helpful when the bindings don't build identically, as unfortunately often happens. + +To use this patch: +- Click details on the `Build o1js bindings / build-bindings-ubunutu` job +- Go to the `patch-upload` job and expand the logs for `Upload patch` +- Download the file linked in the last line of the logs ie. +`Artifact download URL: https://github.com/o1-labs/o1js/actions/runs/12401083741/artifacts/2339952965` +- unzip it +- navigate to `src/bindings` +- run `git apply path/to/bindings.patch` + ## Development ### Branching Policy diff --git a/src/bindings b/src/bindings index f157000fad..74ac5f5e05 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit f157000fadd98f3699ed573ce7a3e3be784f6022 +Subproject commit 74ac5f5e055b66a92cf88b6d9970d5103f1dbaaa From 19886d8e8ab7dd6e3eae34351d4a8892cff8610d Mon Sep 17 00:00:00 2001 From: Geometer1729 <16kuhnb@gmail.com> Date: Thu, 19 Dec 2024 09:30:13 -0500 Subject: [PATCH 323/328] fix link and restore bindings --- .github/workflows/build-bindings.yml | 2 +- src/bindings | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-bindings.yml b/.github/workflows/build-bindings.yml index 4a42d71a0b..4f66ee7c66 100644 --- a/.github/workflows/build-bindings.yml +++ b/.github/workflows/build-bindings.yml @@ -31,7 +31,7 @@ jobs: #fail if this changes any files cd src/bindings echo If this check fails you can download a patch from the patch-upload job - echo "https://github.com/o1-labs/o1js/blob/main/README-dev.md#build-scripts" + echo "https://github.com/o1-labs/o1js/blob/main/README-dev.md#bindings-check-in-ci" git diff --exit-code - name: add build to gc-root if on main if: github.ref == 'refs/heads/main' diff --git a/src/bindings b/src/bindings index 74ac5f5e05..a5a0883f03 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit 74ac5f5e055b66a92cf88b6d9970d5103f1dbaaa +Subproject commit a5a0883f033afd4c9fd4bf96a5e0b8ebd92a87c9 From b4d2d1d842750fbe6b55abe1cc0031e32caf87bc Mon Sep 17 00:00:00 2001 From: Geometer1729 <16kuhnb@gmail.com> Date: Thu, 19 Dec 2024 16:20:05 -0500 Subject: [PATCH 324/328] fix git diff to include .wasm files --- .github/workflows/build-bindings.yml | 2 +- flake.lock | 4 ++-- src/bindings | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-bindings.yml b/.github/workflows/build-bindings.yml index 4f66ee7c66..b4cd18b163 100644 --- a/.github/workflows/build-bindings.yml +++ b/.github/workflows/build-bindings.yml @@ -50,7 +50,7 @@ jobs: run: | cd src/bindings git add . - git diff HEAD > ../../bindings.patch + git diff HEAD --textconv --text > ../../bindings.patch - name: Upload patch uses: actions/upload-artifact@v4 with: diff --git a/flake.lock b/flake.lock index 49061b3547..6fe1645e40 100644 --- a/flake.lock +++ b/flake.lock @@ -265,8 +265,8 @@ "utils": "utils" }, "locked": { - "lastModified": 1733429866, - "narHash": "sha256-/ZEGYdZ2hLjBwdEzG/BIjlDehOjuGWmBqzD55nXfZoY=", + "lastModified": 1734626051, + "narHash": "sha256-4LLy5VMM5TK4LpQXEBiA8ziwYyqGx2ZAuunXGCDpraQ=", "path": "src/mina", "type": "path" }, diff --git a/src/bindings b/src/bindings index e05efb9999..ba0915cd0c 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit e05efb9999dc83107127d6758904e2512eb8582d +Subproject commit ba0915cd0c3ec4bebc46346e5282c2c599c739f8 From 2769561a910abd76a0ec065067574a54a76bf659 Mon Sep 17 00:00:00 2001 From: Geometer1729 <16kuhnb@gmail.com> Date: Thu, 19 Dec 2024 16:37:20 -0500 Subject: [PATCH 325/328] rescramble bindings --- src/bindings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bindings b/src/bindings index ba0915cd0c..6af47f8108 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit ba0915cd0c3ec4bebc46346e5282c2c599c739f8 +Subproject commit 6af47f8108656e32c5017adf4e966b005c4f609b From 00b8671e3a98085a72b8b2da6ef700cb5a9348ba Mon Sep 17 00:00:00 2001 From: Geometer1729 <16kuhnb@gmail.com> Date: Thu, 19 Dec 2024 16:47:29 -0500 Subject: [PATCH 326/328] apply patch from github --- src/bindings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bindings b/src/bindings index 6af47f8108..043f47adf7 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit 6af47f8108656e32c5017adf4e966b005c4f609b +Subproject commit 043f47adf7cd9a48eda4736a2a37df30e433de55 From f9ab3ab1ffc0828f675d108ed2dbad23a10818eb Mon Sep 17 00:00:00 2001 From: hattyhattington17 <181872047+hattyhattington17@users.noreply.github.com> Date: Tue, 7 Jan 2025 14:28:08 -0700 Subject: [PATCH 327/328] apply bindings ci patch --- src/bindings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bindings b/src/bindings index 120fb8d547..14ce3b8f5e 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit 120fb8d54725c4b96bfb7847ddfaf6dfb9344cf7 +Subproject commit 14ce3b8f5e23dbcd9afe3d53304ee84cfc92076b From 8383bb67450ebad9f88ab3fc07ba415799df39ed Mon Sep 17 00:00:00 2001 From: Gregor Date: Wed, 8 Jan 2025 08:21:13 +0100 Subject: [PATCH 328/328] prune imports and changelog fix --- CHANGELOG.md | 2 +- src/lib/proof-system/zkprogram.ts | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6cf58f4d76..8c3f662cba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,7 +25,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - APIs for recursively proving a ZkProgram method from within another https://github.com/o1-labs/o1js/pull/1931 https://github.com/o1-labs/o1js/pull/1932 - `let recursive = Experimental.Recursive(program);` - `recursive.(...args): Promise` - - `recursive..if.(condition, ...args): Promise` + - `recursive..if(condition, ...args): Promise` - This also works within the same program, as long as the return value is type-annotated - Add `enforceTransactionLimits` parameter on Network https://github.com/o1-labs/o1js/issues/1910 - Method for optional types to assert none https://github.com/o1-labs/o1js/pull/1922 diff --git a/src/lib/proof-system/zkprogram.ts b/src/lib/proof-system/zkprogram.ts index 766f7b03fb..01c04322c9 100644 --- a/src/lib/proof-system/zkprogram.ts +++ b/src/lib/proof-system/zkprogram.ts @@ -30,7 +30,6 @@ import { unsetSrsCache, } from '../../bindings/crypto/bindings/srs.js'; import { - ProvablePure, ProvableType, ProvableTypePure, ToProvable, @@ -55,8 +54,7 @@ import { import { emptyWitness } from '../provable/types/util.js'; import { InferValue } from '../../bindings/lib/provable-generic.js'; import { DeclaredProof, ZkProgramContext } from './zkprogram-context.js'; -import { mapObject, mapToObject, zip } from '../util/arrays.js'; -import { Bool } from '../provable/bool.js'; +import { mapObject, mapToObject } from '../util/arrays.js'; // public API export {