From 37f411a59d3b755beb5996834a09501b9136ad6f Mon Sep 17 00:00:00 2001 From: Lydia Garms Date: Tue, 2 Jul 2024 13:53:01 +0100 Subject: [PATCH 01/33] test contract --- test/contracts/KnownUnknown.zol | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 test/contracts/KnownUnknown.zol diff --git a/test/contracts/KnownUnknown.zol b/test/contracts/KnownUnknown.zol new file mode 100644 index 00000000..b235a0fe --- /dev/null +++ b/test/contracts/KnownUnknown.zol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: CC0 +pragma solidity ^0.8.0; +contract Assign { + secret uint256 private a; + secret uint256 private b; + + + function giveAmounttoCharity( uint256 value ) public { + unknown b += value +a; + a+= value; + } + + +} \ No newline at end of file From 17f9ae33708425835d3afffee69b07bb1714e1e0 Mon Sep 17 00:00:00 2001 From: Lydia Garms Date: Tue, 2 Jul 2024 16:42:56 +0100 Subject: [PATCH 02/33] fix: move increments from pre-statements to statements --- .../javascript/raw/boilerplate-generator.ts | 4 +--- .../orchestration/nodejs/toOrchestration.ts | 6 ++++++ test/contracts/KnownUnknown.zol | 11 ++++++++++- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts b/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts index ff13194f..d174299a 100644 --- a/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts +++ b/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts @@ -126,7 +126,6 @@ class BoilerplateGenerator { \n\n// read preimage for incremented state ${stateName}_newOwnerPublicKey = ${newOwnerStatment} ${stateVarIds.join('\n')} - \nconst ${stateName}_newCommitmentValue = generalise(${increment}); \n`]; case 'decrement': if (structProperties) @@ -136,7 +135,6 @@ class BoilerplateGenerator { ${stateVarIds.join('\n')} \nlet ${stateName}_preimage = await getCommitmentsById(${stateName}_stateVarId); \nconst ${stateName}_newCommitmentValue = generalise([${Object.values(increment).map((inc) => `generalise(${inc})`)}]).all; - \nlet [${stateName}_commitmentFlag, ${stateName}_0_oldCommitment, ${stateName}_1_oldCommitment] = getInputCommitments( publicKey.hex(32), ${stateName}_newCommitmentValue.integer, @@ -158,7 +156,7 @@ class BoilerplateGenerator { \n${stateName}_newOwnerPublicKey = ${newOwnerStatment} ${stateVarIds.join('\n')} \nlet ${stateName}_preimage = await getCommitmentsById(${stateName}_stateVarId); - \n const ${stateName}_newCommitmentValue = generalise(${increment}); + // \n const ${stateName}_newCommitmentValue = generalise(${increment}); // First check if required commitments exist or not \nlet [${stateName}_commitmentFlag, ${stateName}_0_oldCommitment, ${stateName}_1_oldCommitment] = getInputCommitments( publicKey.hex(32), diff --git a/src/codeGenerators/orchestration/nodejs/toOrchestration.ts b/src/codeGenerators/orchestration/nodejs/toOrchestration.ts index 595b6edf..ac607d17 100644 --- a/src/codeGenerators/orchestration/nodejs/toOrchestration.ts +++ b/src/codeGenerators/orchestration/nodejs/toOrchestration.ts @@ -122,6 +122,12 @@ export default function codeGenerator(node: any, options: any = {}): any { if (!node.incrementsSecretState && (node.interactsWithSecret || node.expression?.internalFunctionInteractsWithSecret)){ return `\n${codeGenerator(node.expression)};`; } + + if (node.incrementsSecretState && (node.interactsWithSecret || node.expression?.internalFunctionInteractsWithSecret) && !node.expression.leftHandSide.memberName){ + return `\nconst ${node.privateStateName}_newCommitmentValue = generalise(${node.increments}) + \n;`; + } + if (!node.interactsWithSecret) return `\n// non-secret line would go here but has been filtered out`; return `\n// increment would go here but has been filtered out`; diff --git a/test/contracts/KnownUnknown.zol b/test/contracts/KnownUnknown.zol index b235a0fe..5d9d469a 100644 --- a/test/contracts/KnownUnknown.zol +++ b/test/contracts/KnownUnknown.zol @@ -4,9 +4,18 @@ contract Assign { secret uint256 private a; secret uint256 private b; + struct MyStruct { + uint256 prop1; + uint256 prop2; + } + + secret MyStruct public x; + - function giveAmounttoCharity( uint256 value ) public { + function add( uint256 value ) public { unknown b += value +a; + unknown x.prop1 += value + a; + unknown x.prop2 += value + a; a+= value; } From 89d7843b65cec65d71ec939ccd0ef5dbb8854ee2 Mon Sep 17 00:00:00 2001 From: Lydia Garms Date: Tue, 2 Jul 2024 17:38:52 +0100 Subject: [PATCH 03/33] fix: move increments to st atements for incremented structs and add newCommitmentValue to post statements --- .../orchestration/javascript/raw/boilerplate-generator.ts | 6 +++++- src/codeGenerators/orchestration/nodejs/toOrchestration.ts | 6 +++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts b/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts index f07257ff..6832672f 100644 --- a/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts +++ b/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts @@ -119,7 +119,6 @@ class BoilerplateGenerator { \n\n// read preimage for incremented state ${stateName}_newOwnerPublicKey = ${newOwnerStatment} ${stateVarIds.join('\n')} - \nconst ${stateName}_newCommitmentValue = generalise([${Object.values(increment).map((inc) => `generalise(${inc})`)}]).all; \n `]; return [` @@ -380,8 +379,13 @@ class BoilerplateGenerator { // once per state switch (stateType) { case 'increment': + let newComValue = ``; + if (structProperties){ + newComValue = `\nconst ${stateName}_newCommitmentValue = generalise([${Object.values(structProperties).map((sp) => `${stateName}_${sp}_newCommitmentValue`)}]).all;`; + } return [` \nconst ${stateName}_newSalt = generalise(utils.randomHex(31)); + ${newComValue} \nlet ${stateName}_newCommitment = poseidonHash([BigInt(${stateName}_stateVarId), ${structProperties ? `...${stateName}_newCommitmentValue.hex(32).map(v => BigInt(v))` : `BigInt(${stateName}_newCommitmentValue.hex(32))`}, BigInt(${stateName}_newOwnerPublicKey.hex(32)), BigInt(${stateName}_newSalt.hex(32))],); \n${stateName}_newCommitment = generalise(${stateName}_newCommitment.hex(32)); // truncate`]; case 'decrement': diff --git a/src/codeGenerators/orchestration/nodejs/toOrchestration.ts b/src/codeGenerators/orchestration/nodejs/toOrchestration.ts index 658c6415..bc9bc871 100644 --- a/src/codeGenerators/orchestration/nodejs/toOrchestration.ts +++ b/src/codeGenerators/orchestration/nodejs/toOrchestration.ts @@ -124,9 +124,9 @@ export default function codeGenerator(node: any, options: any = {}): any { return `\n${codeGenerator(node.expression)};`; } - if (node.incrementsSecretState && (node.interactsWithSecret || node.expression?.internalFunctionInteractsWithSecret) && !node.expression.leftHandSide.memberName){ - return `\nconst ${node.privateStateName}_newCommitmentValue = generalise(${node.increments}) - \n;`; + if (node.incrementsSecretState && (node.interactsWithSecret || node.expression?.internalFunctionInteractsWithSecret) ){ + let privateStateName = node.privateStateName.replace(/\./g, '_'); + return `\nconst ${privateStateName}_newCommitmentValue = generalise(${node.increments});\n`; } if (!node.interactsWithSecret) From 17ba1e77b2d7c6710cda6bb261b249e6ac87df1a Mon Sep 17 00:00:00 2001 From: Lydia Garms Date: Wed, 3 Jul 2024 09:59:36 +0100 Subject: [PATCH 04/33] fix: move membership witness to the post statements --- .../javascript/raw/boilerplate-generator.ts | 2 +- .../orchestration/nodejs/toOrchestration.ts | 2 +- src/transformers/visitors/toOrchestrationVisitor.ts | 12 +++++++----- test/contracts/KnownUnknown.zol | 7 +++++++ 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts b/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts index 6832672f..3678edf6 100644 --- a/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts +++ b/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts @@ -155,7 +155,7 @@ class BoilerplateGenerator { \n${stateName}_newOwnerPublicKey = ${newOwnerStatment} ${stateVarIds.join('\n')} \nlet ${stateName}_preimage = await getCommitmentsById(${stateName}_stateVarId); - // \n const ${stateName}_newCommitmentValue = generalise(${increment}); + \n const ${stateName}_newCommitmentValue = generalise(${increment}); // First check if required commitments exist or not \nlet [${stateName}_commitmentFlag, ${stateName}_0_oldCommitment, ${stateName}_1_oldCommitment] = getInputCommitments( publicKey.hex(32), diff --git a/src/codeGenerators/orchestration/nodejs/toOrchestration.ts b/src/codeGenerators/orchestration/nodejs/toOrchestration.ts index bc9bc871..2d20d4d9 100644 --- a/src/codeGenerators/orchestration/nodejs/toOrchestration.ts +++ b/src/codeGenerators/orchestration/nodejs/toOrchestration.ts @@ -124,7 +124,7 @@ export default function codeGenerator(node: any, options: any = {}): any { return `\n${codeGenerator(node.expression)};`; } - if (node.incrementsSecretState && (node.interactsWithSecret || node.expression?.internalFunctionInteractsWithSecret) ){ + if (node.incrementsSecretState && (node.interactsWithSecret || node.expression?.internalFunctionInteractsWithSecret) && !node.decrementsSecretState){ let privateStateName = node.privateStateName.replace(/\./g, '_'); return `\nconst ${privateStateName}_newCommitmentValue = generalise(${node.increments});\n`; } diff --git a/src/transformers/visitors/toOrchestrationVisitor.ts b/src/transformers/visitors/toOrchestrationVisitor.ts index 4c950ea5..2e982812 100644 --- a/src/transformers/visitors/toOrchestrationVisitor.ts +++ b/src/transformers/visitors/toOrchestrationVisitor.ts @@ -1015,12 +1015,14 @@ const visitor = { // 9 - WritePreimage - all - per state if (newNodes.readPreimageNode) newFunctionDefinitionNode.body.preStatements.push(newNodes.readPreimageNode); + + if(newNodes.VariableDeclarationStatement) + newFunctionDefinitionNode.body.preStatements.push(newNodes.VariableDeclarationStatement); + if (newNodes.membershipWitnessNode) - newFunctionDefinitionNode.body.preStatements.push( - newNodes.membershipWitnessNode, - ); - if(newNodes.VariableDeclarationStatement) - newFunctionDefinitionNode.body.preStatements.push(newNodes.VariableDeclarationStatement); + newFunctionDefinitionNode.body.postStatements.push( + newNodes.membershipWitnessNode, + ); if (newNodes.calculateNullifierNode) newFunctionDefinitionNode.body.postStatements.push( diff --git a/test/contracts/KnownUnknown.zol b/test/contracts/KnownUnknown.zol index 5d9d469a..7ab7182e 100644 --- a/test/contracts/KnownUnknown.zol +++ b/test/contracts/KnownUnknown.zol @@ -19,5 +19,12 @@ contract Assign { a+= value; } + function remove( uint256 value ) public { + unknown b -= value +a; + unknown x.prop1 -= value + a; + unknown x.prop2 -= value + a; + a+= value; + } + } \ No newline at end of file From f382e6dc98a0f299d07c09e18d7e700670303111 Mon Sep 17 00:00:00 2001 From: Lydia Garms Date: Wed, 3 Jul 2024 14:51:10 +0100 Subject: [PATCH 05/33] fix: move increments for decrementation to statements --- .../javascript/nodes/boilerplate-generator.ts | 6 +- .../javascript/raw/boilerplate-generator.ts | 134 ++++++++++-------- .../javascript/raw/toOrchestration.ts | 13 ++ .../orchestration/nodejs/toOrchestration.ts | 2 +- .../visitors/toOrchestrationVisitor.ts | 1 + 5 files changed, 92 insertions(+), 64 deletions(-) diff --git a/src/boilerplate/orchestration/javascript/nodes/boilerplate-generator.ts b/src/boilerplate/orchestration/javascript/nodes/boilerplate-generator.ts index 537ebeec..278f65c0 100644 --- a/src/boilerplate/orchestration/javascript/nodes/boilerplate-generator.ts +++ b/src/boilerplate/orchestration/javascript/nodes/boilerplate-generator.ts @@ -77,6 +77,7 @@ export function buildPrivateStateNode(nodeType: string, fields: any = {}): any { } case 'MembershipWitness': { const { + id, increment, privateStateName, accessedOnly, @@ -84,10 +85,14 @@ export function buildPrivateStateNode(nodeType: string, fields: any = {}): any { } = fields; return { increment, + stateVarId: id, + isSharedSecret: indicator.isSharedSecret, privateStateName, accessedOnly, isWhole: indicator.isWhole, isPartitioned: indicator.isPartitioned, + structProperties: indicator.isStruct ? Object.keys(indicator.structProperties) : null, + mappingName: indicator.isMapping ? indicator.node?.name : null, }; } case 'CalculateNullifier': { @@ -98,7 +103,6 @@ export function buildPrivateStateNode(nodeType: string, fields: any = {}): any { isSharedSecret: indicator.isSharedSecret, isWhole: indicator.isWhole, isPartitioned: indicator.isPartitioned, - }; } case 'CalculateCommitment': { diff --git a/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts b/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts index 3678edf6..66c25cad 100644 --- a/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts +++ b/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts @@ -105,12 +105,6 @@ class BoilerplateGenerator { accessedOnly, stateVarIds }): string[] { - const stateVarId: string[] = []; - if(stateVarIds.length > 1){ - stateVarId.push((stateVarIds[0].split(" = ")[1]).split(";")[0]); - stateVarId.push(`${stateName}_stateVarId_key`); - } else - stateVarId.push(`${stateName}_stateVarId`); switch (stateType) { case 'increment': @@ -133,21 +127,6 @@ class BoilerplateGenerator { ${stateName}_newOwnerPublicKey = ${newOwnerStatment} ${stateVarIds.join('\n')} \nlet ${stateName}_preimage = await getCommitmentsById(${stateName}_stateVarId); - \nconst ${stateName}_newCommitmentValue = generalise([${Object.values(increment).map((inc) => `generalise(${inc})`)}]).all; - \nlet [${stateName}_commitmentFlag, ${stateName}_0_oldCommitment, ${stateName}_1_oldCommitment] = getInputCommitments( - publicKey.hex(32), - ${stateName}_newCommitmentValue.integer, - ${stateName}_preimage, - true, - ); - - \nlet ${stateName}_witness_0; - \nlet ${stateName}_witness_1; - - const ${stateName}_0_prevSalt = generalise(${stateName}_0_oldCommitment.preimage.salt); - const ${stateName}_1_prevSalt = generalise(${stateName}_1_oldCommitment.preimage.salt); - const ${stateName}_0_prev = generalise(${stateName}_0_oldCommitment.preimage.value); - const ${stateName}_1_prev = generalise(${stateName}_1_oldCommitment.preimage.value); \n `]; return [` @@ -155,46 +134,6 @@ class BoilerplateGenerator { \n${stateName}_newOwnerPublicKey = ${newOwnerStatment} ${stateVarIds.join('\n')} \nlet ${stateName}_preimage = await getCommitmentsById(${stateName}_stateVarId); - \n const ${stateName}_newCommitmentValue = generalise(${increment}); - // First check if required commitments exist or not - \nlet [${stateName}_commitmentFlag, ${stateName}_0_oldCommitment, ${stateName}_1_oldCommitment] = getInputCommitments( - publicKey.hex(32), - ${stateName}_newCommitmentValue.integer, - ${stateName}_preimage, - ); - \nlet ${stateName}_witness_0; - \nlet ${stateName}_witness_1; - - if(${stateName}_1_oldCommitment === null && ${stateName}_commitmentFlag){ - \n${stateName}_witness_0 = await getMembershipWitness('${contractName}', generalise(${stateName}_0_oldCommitment._id).integer); - \n const tx = await splitCommitments('${contractName}', '${mappingName}', ${stateName}_newCommitmentValue, secretKey, publicKey, [${stateVarId.join(' , ')}], ${stateName}_0_oldCommitment, ${stateName}_witness_0, instance, contractAddr, web3); - ${stateName}_preimage = await getCommitmentsById(${stateName}_stateVarId); - - [${stateName}_commitmentFlag, ${stateName}_0_oldCommitment, ${stateName}_1_oldCommitment] = getInputCommitments( - publicKey.hex(32), - ${stateName}_newCommitmentValue.integer, - ${stateName}_preimage, - ); - } - - while(${stateName}_commitmentFlag === false) { - \n${stateName}_witness_0 = await getMembershipWitness('${contractName}', generalise(${stateName}_0_oldCommitment._id).integer); - \n${stateName}_witness_1 = await getMembershipWitness('${contractName}', generalise(${stateName}_1_oldCommitment._id).integer); - - \n const tx = await joinCommitments('${contractName}', '${mappingName}', ${isSharedSecret? `sharedSecretKey, sharedPublicKey`: `secretKey, publicKey`}, [${stateVarId.join(' , ')}], [${stateName}_0_oldCommitment, ${stateName}_1_oldCommitment], [${stateName}_witness_0, ${stateName}_witness_1], instance, contractAddr, web3); - - ${stateName}_preimage = await getCommitmentsById(${stateName}_stateVarId); - - [${stateName}_commitmentFlag, ${stateName}_0_oldCommitment, ${stateName}_1_oldCommitment] = getInputCommitments( - ${isSharedSecret ? `sharedPublicKey.hex(32)` : `publicKey.hex(32)`}, - ${stateName}_newCommitmentValue.integer, - ${stateName}_preimage, - ); - } - const ${stateName}_0_prevSalt = generalise(${stateName}_0_oldCommitment.preimage.salt); - const ${stateName}_1_prevSalt = generalise(${stateName}_1_oldCommitment.preimage.salt); - const ${stateName}_0_prev = generalise(${stateName}_0_oldCommitment.preimage.value); - const ${stateName}_1_prev = generalise(${stateName}_1_oldCommitment.preimage.value); \n` ]; case 'whole': switch (reinitialisedOnly) { @@ -234,10 +173,33 @@ class BoilerplateGenerator { membershipWitness = { postStatements({ stateName, contractName, - stateType }): string[] { + stateType, mappingName, structProperties, isSharedSecret, stateVarIds }): string[] { + const stateVarId: string[] = []; + if(stateVarIds.length > 1){ + stateVarId.push((stateVarIds[0].split(" = ")[1]).split(";")[0]); + stateVarId.push(`${stateName}_stateVarId_key`); + } else + stateVarId.push(`${stateName}_stateVarId`); switch (stateType) { case 'partitioned': + if (structProperties) return [` + \n\n// First check if required commitments exist or not + \nconst ${stateName}_newCommitmentValue = generalise([${Object.values(structProperties).map((sp) => `${stateName}_${sp}_newCommitmentValue`)}]).all; + \nlet [${stateName}_commitmentFlag, ${stateName}_0_oldCommitment, ${stateName}_1_oldCommitment] = getInputCommitments( + publicKey.hex(32), + ${stateName}_newCommitmentValue.integer, + ${stateName}_preimage, + true, + ); + + \nlet ${stateName}_witness_0; + \nlet ${stateName}_witness_1; + + const ${stateName}_0_prevSalt = generalise(${stateName}_0_oldCommitment.preimage.salt); + const ${stateName}_1_prevSalt = generalise(${stateName}_1_oldCommitment.preimage.salt); + const ${stateName}_0_prev = generalise(${stateName}_0_oldCommitment.preimage.value); + const ${stateName}_1_prev = generalise(${stateName}_1_oldCommitment.preimage.value); \n\n// generate witness for partitioned state ${stateName}_witness_0 = await getMembershipWitness('${contractName}', generalise(${stateName}_0_oldCommitment._id).integer); ${stateName}_witness_1 = await getMembershipWitness('${contractName}', generalise(${stateName}_1_oldCommitment._id).integer); @@ -246,6 +208,54 @@ class BoilerplateGenerator { const ${stateName}_root = generalise(${stateName}_witness_0.root); const ${stateName}_0_path = generalise(${stateName}_witness_0.path).all; const ${stateName}_1_path = generalise(${stateName}_witness_1.path).all;\n`]; + return [` + \n\n// First check if required commitments exist or not + \nlet [${stateName}_commitmentFlag, ${stateName}_0_oldCommitment, ${stateName}_1_oldCommitment] = getInputCommitments( + publicKey.hex(32), + ${stateName}_newCommitmentValue.integer, + ${stateName}_preimage, + ); + \nlet ${stateName}_witness_0; + \nlet ${stateName}_witness_1; + + if(${stateName}_1_oldCommitment === null && ${stateName}_commitmentFlag){ + \n${stateName}_witness_0 = await getMembershipWitness('${contractName}', generalise(${stateName}_0_oldCommitment._id).integer); + \n const tx = await splitCommitments('${contractName}', '${mappingName}', ${stateName}_newCommitmentValue, secretKey, publicKey, [${stateVarId.join(' , ')}], ${stateName}_0_oldCommitment, ${stateName}_witness_0, instance, contractAddr, web3); + ${stateName}_preimage = await getCommitmentsById(${stateName}_stateVarId); + + [${stateName}_commitmentFlag, ${stateName}_0_oldCommitment, ${stateName}_1_oldCommitment] = getInputCommitments( + publicKey.hex(32), + ${stateName}_newCommitmentValue.integer, + ${stateName}_preimage, + ); + } + + while(${stateName}_commitmentFlag === false) { + \n${stateName}_witness_0 = await getMembershipWitness('${contractName}', generalise(${stateName}_0_oldCommitment._id).integer); + \n${stateName}_witness_1 = await getMembershipWitness('${contractName}', generalise(${stateName}_1_oldCommitment._id).integer); + + \n const tx = await joinCommitments('${contractName}', '${mappingName}', ${isSharedSecret? `sharedSecretKey, sharedPublicKey`: `secretKey, publicKey`}, [${stateVarId.join(' , ')}], [${stateName}_0_oldCommitment, ${stateName}_1_oldCommitment], [${stateName}_witness_0, ${stateName}_witness_1], instance, contractAddr, web3); + + ${stateName}_preimage = await getCommitmentsById(${stateName}_stateVarId); + + [${stateName}_commitmentFlag, ${stateName}_0_oldCommitment, ${stateName}_1_oldCommitment] = getInputCommitments( + ${isSharedSecret ? `sharedPublicKey.hex(32)` : `publicKey.hex(32)`}, + ${stateName}_newCommitmentValue.integer, + ${stateName}_preimage, + ); + } + const ${stateName}_0_prevSalt = generalise(${stateName}_0_oldCommitment.preimage.salt); + const ${stateName}_1_prevSalt = generalise(${stateName}_1_oldCommitment.preimage.salt); + const ${stateName}_0_prev = generalise(${stateName}_0_oldCommitment.preimage.value); + const ${stateName}_1_prev = generalise(${stateName}_1_oldCommitment.preimage.value); + \n\n// generate witness for partitioned state + ${stateName}_witness_0 = await getMembershipWitness('${contractName}', generalise(${stateName}_0_oldCommitment._id).integer); + ${stateName}_witness_1 = await getMembershipWitness('${contractName}', generalise(${stateName}_1_oldCommitment._id).integer); + const ${stateName}_0_index = generalise(${stateName}_witness_0.index); + const ${stateName}_1_index = generalise(${stateName}_witness_1.index); + const ${stateName}_root = generalise(${stateName}_witness_0.root); + const ${stateName}_0_path = generalise(${stateName}_witness_0.path).all; + const ${stateName}_1_path = generalise(${stateName}_witness_1.path).all;\n`]; case 'whole': return [` \n\n// generate witness for whole state diff --git a/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts b/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts index 328a3e02..1235a0da 100644 --- a/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts +++ b/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts @@ -686,6 +686,7 @@ export const OrchestrationCodeBoilerPlate: any = (node: any) => { case 'MembershipWitness': for ([stateName, stateNode] of Object.entries(node.privateStates)) { + const stateVarIds = stateVariableIds({ stateName, stateNode }); if (node.isConstructor) { lines.push([` const ${stateName}_index = generalise(0); @@ -700,6 +701,10 @@ export const OrchestrationCodeBoilerPlate: any = (node: any) => { stateName, contractName: node.contractName, stateType: 'partitioned', + mappingName: stateNode.mappingName || stateName, + structProperties: stateNode.structProperties, + isSharedSecret: stateNode.isSharedSecret, + stateVarIds })); } @@ -709,6 +714,10 @@ export const OrchestrationCodeBoilerPlate: any = (node: any) => { stateName, contractName: node.contractName, stateType: 'accessedOnly', + mappingName: stateNode.mappingName || stateName, + structProperties: stateNode.structProperties, + isSharedSecret: stateNode.isSharedSecret, + stateVarIds })); } else if (stateNode.isWhole) { @@ -717,6 +726,10 @@ export const OrchestrationCodeBoilerPlate: any = (node: any) => { stateName, contractName: node.contractName, stateType: 'whole', + mappingName: stateNode.mappingName || stateName, + structProperties: stateNode.structProperties, + isSharedSecret: stateNode.isSharedSecret, + stateVarIds })); } diff --git a/src/codeGenerators/orchestration/nodejs/toOrchestration.ts b/src/codeGenerators/orchestration/nodejs/toOrchestration.ts index 2d20d4d9..f5d23ebb 100644 --- a/src/codeGenerators/orchestration/nodejs/toOrchestration.ts +++ b/src/codeGenerators/orchestration/nodejs/toOrchestration.ts @@ -124,7 +124,7 @@ export default function codeGenerator(node: any, options: any = {}): any { return `\n${codeGenerator(node.expression)};`; } - if (node.incrementsSecretState && (node.interactsWithSecret || node.expression?.internalFunctionInteractsWithSecret) && !node.decrementsSecretState){ + if (node.incrementsSecretState && (node.interactsWithSecret || node.expression?.internalFunctionInteractsWithSecret)){ let privateStateName = node.privateStateName.replace(/\./g, '_'); return `\nconst ${privateStateName}_newCommitmentValue = generalise(${node.increments});\n`; } diff --git a/src/transformers/visitors/toOrchestrationVisitor.ts b/src/transformers/visitors/toOrchestrationVisitor.ts index 2e982812..e53d0aec 100644 --- a/src/transformers/visitors/toOrchestrationVisitor.ts +++ b/src/transformers/visitors/toOrchestrationVisitor.ts @@ -715,6 +715,7 @@ const visitor = { newNodes.membershipWitnessNode.privateStates[ name ] = buildPrivateStateNode('MembershipWitness', { + id, privateStateName: name, indicator: stateVarIndicator, accessedOnly, From 03f40011150d4f1c2b6a617bebed60ee5fff860f Mon Sep 17 00:00:00 2001 From: Lydia Garms Date: Wed, 3 Jul 2024 15:25:42 +0100 Subject: [PATCH 06/33] fix: move membership witnes from pre-statements to post statements in orchestrationinternalfunctioncallvisitor --- ...rchestrationInternalFunctionCallVisitor.ts | 52 +++++++++++-------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts b/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts index a2ea0567..e55a42dd 100644 --- a/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts +++ b/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts @@ -45,7 +45,7 @@ const internalCallVisitor = { } state.newPreStatementList = cloneDeep(childNode.body.preStatements); state.newPreStatementList.forEach(node => { - if(['InitialisePreimage','ReadPreimage','MembershipWitness'].includes(node.nodeType)) { + if(['InitialisePreimage','ReadPreimage'].includes(node.nodeType)) { let stateName: string; let stateNode: any; let newstateName: string; @@ -75,10 +75,6 @@ const internalCallVisitor = { stateNode.stateVarId[1] = stateNode.stateVarId[1].replace(oldStateName, state.newStateArray[name][index]) break; } - case 'MembershipWitness': { - stateNode.privateStateName = stateNode.privateStateName.replace('_'+oldStateName, '_'+ state.newStateArray[name][index]) - break; - } default : break; } @@ -106,6 +102,20 @@ const internalCallVisitor = { }); state.newPostStatementList = cloneDeep(childNode.body.postStatements); state.newPostStatementList.forEach(node => { + if(node.nodeType === 'MembershipWitness'){ + let stateName: string; + let stateNode: any; + let newstateName: string; + for( [stateName, stateNode] of Object.entries(node.privateStates)){ + for(const [index, oldStateName] of state.oldStateArray[name].entries()) { + newstateName = stateName.replace('_'+oldStateName, '_'+ state.newStateArray[name][index]) + if(newstateName != stateName ){ + node.privateStates[ newstateName ] = node.privateStates[stateName]; + delete(node.privateStates[ stateName ]); + } + } + } + } if(node.nodeType === 'CalculateNullifier'){ let stateName: string; let stateNode: any; @@ -238,22 +248,6 @@ const internalCallVisitor = { }); break; } - case 'MembershipWitness': { - state.newPreStatementList.forEach(statenode => { - if(statenode.nodeType === 'MembershipWitness'){ - Object.keys(node.privateStates).forEach(key => { - Object.keys(statenode.privateStates).forEach(newKey => { - if (key === newKey){ - statenode.privateStates[newKey].accessedOnly = statenode.privateStates[newKey].accessedOnly && node.privateStates[key].accessedOnly; - statenode.privateStates[newKey].nullifierRequired = statenode.privateStates[newKey].nullifierRequired || node.privateStates[key].nullifierRequired; - } - }); - }); - node.privateStates = Object.assign(node.privateStates,statenode.privateStates) - } - }); - break; - } default : break; } @@ -340,6 +334,22 @@ const internalCallVisitor = { childNode.body.postStatements.forEach(node => { switch(node.nodeType) { + case 'MembershipWitness' : { + state.newPostStatementList.forEach(statenode => { + if(statenode.nodeType === 'MembershipWitness'){ + Object.keys(node.privateStates).forEach(key => { + Object.keys(statenode.privateStates).forEach(newKey => { + if (key === newKey){ + statenode.privateStates[newKey].accessedOnly = statenode.privateStates[newKey].accessedOnly && node.privateStates[key].accessedOnly; + statenode.privateStates[newKey].nullifierRequired = statenode.privateStates[newKey].nullifierRequired || node.privateStates[key].nullifierRequired; + } + }); + }); + node.privateStates = Object.assign(node.privateStates,statenode.privateStates); + } + }); + break; + } case 'CalculateNullifier' : { state.newPostStatementList.forEach(statenode => { if(statenode.nodeType === 'CalculateNullifier'){ From 8535fde78759dc7756780c7213ec412a547e32a1 Mon Sep 17 00:00:00 2001 From: Lydia Garms Date: Wed, 3 Jul 2024 15:35:54 +0100 Subject: [PATCH 07/33] fix: error causing zappify error --- src/boilerplate/orchestration/javascript/raw/toOrchestration.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts b/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts index 1235a0da..2cb99a77 100644 --- a/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts +++ b/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts @@ -686,7 +686,7 @@ export const OrchestrationCodeBoilerPlate: any = (node: any) => { case 'MembershipWitness': for ([stateName, stateNode] of Object.entries(node.privateStates)) { - const stateVarIds = stateVariableIds({ stateName, stateNode }); + const stateVarIds = stateVariableIds({ privateStateName: stateName, stateNode }); if (node.isConstructor) { lines.push([` const ${stateName}_index = generalise(0); From ac8f7825f7e037bb72c269d21443774493024bce Mon Sep 17 00:00:00 2001 From: Lydia Garms Date: Wed, 3 Jul 2024 16:45:17 +0100 Subject: [PATCH 08/33] fix: zappify error in SimpleStruct2 because node.increments is a struct --- src/codeGenerators/orchestration/nodejs/toOrchestration.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/codeGenerators/orchestration/nodejs/toOrchestration.ts b/src/codeGenerators/orchestration/nodejs/toOrchestration.ts index f5d23ebb..ce480e5c 100644 --- a/src/codeGenerators/orchestration/nodejs/toOrchestration.ts +++ b/src/codeGenerators/orchestration/nodejs/toOrchestration.ts @@ -126,6 +126,12 @@ export default function codeGenerator(node: any, options: any = {}): any { if (node.incrementsSecretState && (node.interactsWithSecret || node.expression?.internalFunctionInteractsWithSecret)){ let privateStateName = node.privateStateName.replace(/\./g, '_'); + if (typeof node.increments === 'object' && node.increments !== null) { + if (node.expression.leftHandSide.nodeType === 'MemberAccess'){ + let propName = node.expression.leftHandSide.memberName; + return `\nconst ${privateStateName}_newCommitmentValue = generalise(${node.increments[propName]});\n`; + } + }; return `\nconst ${privateStateName}_newCommitmentValue = generalise(${node.increments});\n`; } From d9369a5ff84ef3b7e2c99cad5675aaeffb5ee1d0 Mon Sep 17 00:00:00 2001 From: Lydia Garms Date: Thu, 4 Jul 2024 16:39:13 +0100 Subject: [PATCH 09/33] move increments and decrements into statements in circuits --- .../zokrates/nodes/BoilerplateGenerator.ts | 10 ++- .../zokrates/raw/BoilerplateGenerator.ts | 65 +++++++++++-------- src/transformers/visitors/toCircuitVisitor.ts | 6 ++ test/contracts/KnownUnknown.zol | 5 +- 4 files changed, 54 insertions(+), 32 deletions(-) diff --git a/src/boilerplate/circuit/zokrates/nodes/BoilerplateGenerator.ts b/src/boilerplate/circuit/zokrates/nodes/BoilerplateGenerator.ts index 591274fe..20d823c8 100644 --- a/src/boilerplate/circuit/zokrates/nodes/BoilerplateGenerator.ts +++ b/src/boilerplate/circuit/zokrates/nodes/BoilerplateGenerator.ts @@ -376,18 +376,24 @@ class BoilerplateGenerator { }); /** Partitioned states need boilerplate for an incrementation/decrementation, because it's so weird and different from `a = a - b`. Whole states inherit directly from the AST, so don't need boilerplate here. */ - incrementation = () => { + incrementation = (extraParams) => { //const startIndex = this.getIndex({ addendId }); return { // startIndex, + newCommitmentValue: this.newCommitmentValue, + structProperties: (this.isStruct && { structProperties: this.structProperties}), + memberName: extraParams.memberName, addend: {}, }; }; - decrementation = () => { + decrementation = (extraParams) => { //const startIndex = this.getIndex({ subtrahendId }); return { // startIndex, + newCommitmentValue: this.newCommitmentValue, + structProperties: (this.isStruct && { structProperties: this.structProperties}), + memberName: extraParams.memberName, subtrahend: {}, }; }; diff --git a/src/boilerplate/circuit/zokrates/raw/BoilerplateGenerator.ts b/src/boilerplate/circuit/zokrates/raw/BoilerplateGenerator.ts index 30d87268..894f142f 100644 --- a/src/boilerplate/circuit/zokrates/raw/BoilerplateGenerator.ts +++ b/src/boilerplate/circuit/zokrates/raw/BoilerplateGenerator.ts @@ -310,10 +310,20 @@ class BoilerplateGenerator { ]; }, - preStatements({ name: x, id, isMapping }): string[] { + preStatements({ name: x, id, isMapping, isWhole, isNullified, typeName, structProperties }): string[] { if (isMapping) return []; + let decLine = ''; + if (!isWhole && isNullified) { + const i = parseInt(x.slice(-1), 10); + const x0 = x.slice(0, -1) + `${i-2}`; + const x1 = x.slice(0, -1) + `${i-1}`; + const x_name = x.slice(0, -2); + let type = typeName ? typeName : 'field'; + decLine = `${type} ${x_name} = ${structProperties ? `${type} {${structProperties.map(p => ` ${p}: ${x0}.${p} + ${x1}.${p}`)}}` :`${x0} + ${x1}`} `; + } return [ - ` + `${decLine} + \n // We need to hard-code each stateVarId into the circuit: field ${x}_stateVarId_field = ${id}`, // TODO: this results in unnecessary unpacking constraints, but simplifies transpilation effort, for now. @@ -322,30 +332,32 @@ class BoilerplateGenerator { postStatements({ name: x, isWhole, isNullified, newCommitmentValue, structProperties, structPropertiesTypes, typeName }): string[] { // if (!isWhole && !newCommitmentValue) throw new Error('PATH'); - const y = isWhole ? x : newCommitmentValue; + let y = isWhole ? x : newCommitmentValue; const lines: string[] = []; if (!isWhole && isNullified) { // decrement const i = parseInt(x.slice(-1), 10); const x0 = x.slice(0, -1) + `${i-2}`; const x1 = x.slice(0, -1) + `${i-1}`; + const x_name = x.slice(0, -2); if (!structProperties) { lines.push( - `assert(${x0} + ${x1} > ${y}) + `assert(${x_name} >0) // TODO: assert no under/overflows - field ${x}_newCommitment_value_field = (${x0} + ${x1}) - (${y})` + field ${x}_newCommitment_value_field = ${x_name}` ); } else { // TODO types for each structProperty lines.push( - `${structProperties.map(p => newCommitmentValue[p] === '0' ? '' : `assert(${x0}.${p} + ${x1}.${p} >= ${y[p]})`).join('\n')} + `${structProperties.map(p => newCommitmentValue[p] === '0' ? '' : `assert(${x_name}.${p} > 0)`).join('\n')} // TODO: assert no under/overflows - ${typeName} ${x}_newCommitment_value = ${typeName} { ${structProperties.map(p => ` ${p}: (${x0}.${p} + ${x1}.${p}) - (${y[p]})`)} }` + ${typeName} ${x}_newCommitment_value = ${typeName} { ${structProperties.map(p => ` ${p}: ${x_name}.${p}`)} }` ); } } else { + y = isWhole ? x : x.slice(0, -2); if (!structProperties ) { if (typeName === 'bool'){ lines.push(`field ${x}_newCommitment_value_field = if ${y} then 1 else 0 fi`); @@ -355,7 +367,7 @@ class BoilerplateGenerator { } else { - lines.push(`${typeName} ${x}_newCommitment_value = ${typeName} { ${structProperties.map(p => ` ${p}: ${isWhole ? `${y}.${p}` : `${y[p]}`}`)} }\n`); + lines.push(`${typeName} ${x}_newCommitment_value = ${typeName} { ${structProperties.map(p => ` ${p}: ${isWhole ? `${y}.${p}` : `${y}_${p}`}`)} }\n`); if (structPropertiesTypes) { structPropertiesTypes.forEach(property => { if (property.typeName === 'bool'){ @@ -509,22 +521,17 @@ class BoilerplateGenerator { return []; // TODO: we might eventually import some underflow/overflow functions. }, - statements({ name: x}): string[] { - // let y = codeGenerator(addends[0]); - // - // for (const addend of addends) { - // if (addend !== addend[0]) - // y += `${addend.precedingOperator} ${codeGenerator(addend)}`; - // } - - - return [ - `// Skipping incrementation of ${x}` + statements({ name: x, addend, newCommitmentValue, structProperties, memberName}): string[] { + let typeName = 'field'; + if (addend.typeName?.name === 'bool' || addend.leftExpression?.typeName?.name === 'bool') typeName = 'bool'; + if (structProperties) { + return [`${typeName} ${x}_${memberName} = ${x}_${memberName} + ${newCommitmentValue[memberName]}`] + } + return [`${typeName} ${x} = ${x} + ${newCommitmentValue}`]; + //return [ + // `// Skipping incrementation of ${x}` // ` - // // The below represents the incrementation '${x} = ${x} + ${y}': - // - // field ${x}_${i} = ${y}`, - ]; + //]; }, }; @@ -534,15 +541,19 @@ class BoilerplateGenerator { return []; // TODO: we might eventually import some underflow/overflow functions. }, - statements({ name: x }): string[] { + statements({ name: x, subtrahend, newCommitmentValue, structProperties, memberName}): string[] { + if (structProperties) { + return [`${x}.${memberName} = ${newCommitmentValue[memberName]}`] + } + return [`${x} = ${x} - (${newCommitmentValue})`]; // const y = codeGenerator(subtrahend); // let i = startIndex; // const x0 = `${x}_${i++}`; // const x1 = `${x}_${i++}`; // const x2 = `${x}_${i}`; - return [ - `// Moved decrementation of ${x}` + //return [ + //`// Moved decrementation of ${x}` // ` // // The below represents the decrementation '${x} = ${x} - ${y}': // @@ -550,7 +561,7 @@ class BoilerplateGenerator { // // TODO: assert no under/overflows // // field ${x2} = (${x0} + ${x1}) - ${y}`, - ]; + //]; }, }; internalFunctionCall = { diff --git a/src/transformers/visitors/toCircuitVisitor.ts b/src/transformers/visitors/toCircuitVisitor.ts index 7ebf558a..655587a4 100644 --- a/src/transformers/visitors/toCircuitVisitor.ts +++ b/src/transformers/visitors/toCircuitVisitor.ts @@ -854,6 +854,9 @@ let childOfSecret = path.getAncestorOfType('ForStatement')?.containsSecret; lhs.indexExpression?.name || lhs.indexExpression.expression.name, }), // TODO: tidy this + ...(lhsIndicator.isStruct && { + memberName: lhs.memberName + }), }); tempRHSPath.containerName = 'subtrahend'; // a dangerous bodge that works node._newASTPointer = newNode.subtrahend; @@ -868,6 +871,9 @@ let childOfSecret = path.getAncestorOfType('ForStatement')?.containsSecret; lhs.indexExpression?.name || lhs.indexExpression.expression.name, }), // TODO: tidy this + ...(lhsIndicator.isStruct && { + memberName: lhs.memberName + }), }); tempRHSPath.containerName = 'addend'; // a dangerous bodge that works node._newASTPointer = newNode.addend; diff --git a/test/contracts/KnownUnknown.zol b/test/contracts/KnownUnknown.zol index 7ab7182e..afa4d477 100644 --- a/test/contracts/KnownUnknown.zol +++ b/test/contracts/KnownUnknown.zol @@ -15,16 +15,15 @@ contract Assign { function add( uint256 value ) public { unknown b += value +a; unknown x.prop1 += value + a; - unknown x.prop2 += value + a; + unknown x.prop2 += value; a+= value; } function remove( uint256 value ) public { unknown b -= value +a; unknown x.prop1 -= value + a; - unknown x.prop2 -= value + a; + unknown x.prop2 -= value; a+= value; } - } \ No newline at end of file From 41baade443a03d1fd5bc5611757b53337fa0c869 Mon Sep 17 00:00:00 2001 From: Lydia Garms Date: Thu, 4 Jul 2024 17:59:56 +0100 Subject: [PATCH 10/33] fix: incrementation variables declared at beginning in circuit --- .../zokrates/raw/BoilerplateGenerator.ts | 24 +++++++++---------- test/contracts/KnownUnknown.zol | 2 ++ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/boilerplate/circuit/zokrates/raw/BoilerplateGenerator.ts b/src/boilerplate/circuit/zokrates/raw/BoilerplateGenerator.ts index 894f142f..02055320 100644 --- a/src/boilerplate/circuit/zokrates/raw/BoilerplateGenerator.ts +++ b/src/boilerplate/circuit/zokrates/raw/BoilerplateGenerator.ts @@ -320,6 +320,10 @@ class BoilerplateGenerator { const x_name = x.slice(0, -2); let type = typeName ? typeName : 'field'; decLine = `${type} ${x_name} = ${structProperties ? `${type} {${structProperties.map(p => ` ${p}: ${x0}.${p} + ${x1}.${p}`)}}` :`${x0} + ${x1}`} `; + } else if (!isWhole){ + const x_name = x.slice(0, -2); + let type = typeName ? typeName : 'field'; + decLine = `${type} ${x_name} = ${structProperties ? `${type} {${structProperties.map(p => ` ${p}: 0`)}}` :`0`} `; } return [ `${decLine} @@ -332,32 +336,30 @@ class BoilerplateGenerator { postStatements({ name: x, isWhole, isNullified, newCommitmentValue, structProperties, structPropertiesTypes, typeName }): string[] { // if (!isWhole && !newCommitmentValue) throw new Error('PATH'); - let y = isWhole ? x : newCommitmentValue; + let y = isWhole ? x : x.slice(0, -2); const lines: string[] = []; if (!isWhole && isNullified) { // decrement const i = parseInt(x.slice(-1), 10); const x0 = x.slice(0, -1) + `${i-2}`; const x1 = x.slice(0, -1) + `${i-1}`; - const x_name = x.slice(0, -2); if (!structProperties) { lines.push( - `assert(${x_name} >0) + `assert(${y} >0) // TODO: assert no under/overflows - field ${x}_newCommitment_value_field = ${x_name}` + field ${x}_newCommitment_value_field = ${y}` ); } else { // TODO types for each structProperty lines.push( - `${structProperties.map(p => newCommitmentValue[p] === '0' ? '' : `assert(${x_name}.${p} > 0)`).join('\n')} + `${structProperties.map(p => newCommitmentValue[p] === '0' ? '' : `assert(${y}.${p} > 0)`).join('\n')} // TODO: assert no under/overflows - ${typeName} ${x}_newCommitment_value = ${typeName} { ${structProperties.map(p => ` ${p}: ${x_name}.${p}`)} }` + ${typeName} ${x}_newCommitment_value = ${typeName} { ${structProperties.map(p => ` ${p}: ${y}.${p}`)} }` ); } } else { - y = isWhole ? x : x.slice(0, -2); if (!structProperties ) { if (typeName === 'bool'){ lines.push(`field ${x}_newCommitment_value_field = if ${y} then 1 else 0 fi`); @@ -522,12 +524,10 @@ class BoilerplateGenerator { }, statements({ name: x, addend, newCommitmentValue, structProperties, memberName}): string[] { - let typeName = 'field'; - if (addend.typeName?.name === 'bool' || addend.leftExpression?.typeName?.name === 'bool') typeName = 'bool'; if (structProperties) { - return [`${typeName} ${x}_${memberName} = ${x}_${memberName} + ${newCommitmentValue[memberName]}`] + return [`${x}.${memberName} = ${x}.${memberName} + ${newCommitmentValue[memberName]}`] } - return [`${typeName} ${x} = ${x} + ${newCommitmentValue}`]; + return [`${x} = ${x} + ${newCommitmentValue}`]; //return [ // `// Skipping incrementation of ${x}` // ` @@ -543,7 +543,7 @@ class BoilerplateGenerator { statements({ name: x, subtrahend, newCommitmentValue, structProperties, memberName}): string[] { if (structProperties) { - return [`${x}.${memberName} = ${newCommitmentValue[memberName]}`] + return [`${x}.${memberName} = ${x}.${memberName} - ${newCommitmentValue[memberName]}`] } return [`${x} = ${x} - (${newCommitmentValue})`]; // const y = codeGenerator(subtrahend); diff --git a/test/contracts/KnownUnknown.zol b/test/contracts/KnownUnknown.zol index afa4d477..0f30df65 100644 --- a/test/contracts/KnownUnknown.zol +++ b/test/contracts/KnownUnknown.zol @@ -16,6 +16,8 @@ contract Assign { unknown b += value +a; unknown x.prop1 += value + a; unknown x.prop2 += value; + unknown b += value; + unknown x.prop1 += value ; a+= value; } From ca29a16e24672e4e9bd0b08d637226888995d040 Mon Sep 17 00:00:00 2001 From: Lydia Garms Date: Thu, 4 Jul 2024 18:22:49 +0100 Subject: [PATCH 11/33] fix: zappify error in whol-increment due to duplicate state var id in circuit --- .../circuit/zokrates/raw/BoilerplateGenerator.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/boilerplate/circuit/zokrates/raw/BoilerplateGenerator.ts b/src/boilerplate/circuit/zokrates/raw/BoilerplateGenerator.ts index 02055320..81138b3d 100644 --- a/src/boilerplate/circuit/zokrates/raw/BoilerplateGenerator.ts +++ b/src/boilerplate/circuit/zokrates/raw/BoilerplateGenerator.ts @@ -324,6 +324,13 @@ class BoilerplateGenerator { const x_name = x.slice(0, -2); let type = typeName ? typeName : 'field'; decLine = `${type} ${x_name} = ${structProperties ? `${type} {${structProperties.map(p => ` ${p}: 0`)}}` :`0`} `; + } else{ + return [ + ` + // We need to hard-code each stateVarId into the circuit: + field ${x}_stateVarId_field = ${id}`, + // TODO: this results in unnecessary unpacking constraints, but simplifies transpilation effort, for now. + ]; } return [ `${decLine} From 3877b0032f1e31cb96b90fed2ad241d80852b2a7 Mon Sep 17 00:00:00 2001 From: Lydia Garms Date: Fri, 5 Jul 2024 10:09:25 +0100 Subject: [PATCH 12/33] fix: circuit error in Assign-Shared-Secret due to mappings --- src/boilerplate/circuit/zokrates/nodes/BoilerplateGenerator.ts | 2 +- src/boilerplate/circuit/zokrates/raw/BoilerplateGenerator.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/boilerplate/circuit/zokrates/nodes/BoilerplateGenerator.ts b/src/boilerplate/circuit/zokrates/nodes/BoilerplateGenerator.ts index 20d823c8..0254c5ad 100644 --- a/src/boilerplate/circuit/zokrates/nodes/BoilerplateGenerator.ts +++ b/src/boilerplate/circuit/zokrates/nodes/BoilerplateGenerator.ts @@ -231,7 +231,7 @@ class BoilerplateGenerator { const { mappingKeyName } = extraParams; this.refresh(mappingKeyName); } - + this.initialise(this.indicators); return { nodeType: 'BoilerplateStatement', bpSection: 'statements', diff --git a/src/boilerplate/circuit/zokrates/raw/BoilerplateGenerator.ts b/src/boilerplate/circuit/zokrates/raw/BoilerplateGenerator.ts index 81138b3d..60bd73f3 100644 --- a/src/boilerplate/circuit/zokrates/raw/BoilerplateGenerator.ts +++ b/src/boilerplate/circuit/zokrates/raw/BoilerplateGenerator.ts @@ -311,7 +311,7 @@ class BoilerplateGenerator { }, preStatements({ name: x, id, isMapping, isWhole, isNullified, typeName, structProperties }): string[] { - if (isMapping) return []; + if (isMapping && isWhole) return []; let decLine = ''; if (!isWhole && isNullified) { const i = parseInt(x.slice(-1), 10); From 8a48d465f3a6c4e551eb4cf5c5a114f056630e89 Mon Sep 17 00:00:00 2001 From: Lydia Garms Date: Fri, 5 Jul 2024 11:46:35 +0100 Subject: [PATCH 13/33] fix: zappify errors due to multiple declarations of state var id in circuit --- .../circuit/zokrates/raw/BoilerplateGenerator.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/boilerplate/circuit/zokrates/raw/BoilerplateGenerator.ts b/src/boilerplate/circuit/zokrates/raw/BoilerplateGenerator.ts index 60bd73f3..cdd792a1 100644 --- a/src/boilerplate/circuit/zokrates/raw/BoilerplateGenerator.ts +++ b/src/boilerplate/circuit/zokrates/raw/BoilerplateGenerator.ts @@ -313,6 +313,10 @@ class BoilerplateGenerator { preStatements({ name: x, id, isMapping, isWhole, isNullified, typeName, structProperties }): string[] { if (isMapping && isWhole) return []; let decLine = ''; + let stateVarIdLine = ``; + if (!isMapping) stateVarIdLine = ` + // We need to hard-code each stateVarId into the circuit: + field ${x}_stateVarId_field = ${id}`; if (!isWhole && isNullified) { const i = parseInt(x.slice(-1), 10); const x0 = x.slice(0, -1) + `${i-2}`; @@ -325,18 +329,14 @@ class BoilerplateGenerator { let type = typeName ? typeName : 'field'; decLine = `${type} ${x_name} = ${structProperties ? `${type} {${structProperties.map(p => ` ${p}: 0`)}}` :`0`} `; } else{ - return [ - ` + return [` // We need to hard-code each stateVarId into the circuit: - field ${x}_stateVarId_field = ${id}`, - // TODO: this results in unnecessary unpacking constraints, but simplifies transpilation effort, for now. - ]; + field ${x}_stateVarId_field = ${id}`]; } return [ `${decLine} \n - // We need to hard-code each stateVarId into the circuit: - field ${x}_stateVarId_field = ${id}`, + ${stateVarIdLine}`, // TODO: this results in unnecessary unpacking constraints, but simplifies transpilation effort, for now. ]; }, From 06addb42a5ac90e5af1930c5a5800dc469784ecf Mon Sep 17 00:00:00 2001 From: Lydia Garms Date: Fri, 5 Jul 2024 14:13:45 +0100 Subject: [PATCH 14/33] allow for multiple incrementations --- .../zokrates/nodes/BoilerplateGenerator.ts | 22 ++++++++++++------- src/traverse/Indicator.ts | 10 +++++++++ 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/boilerplate/circuit/zokrates/nodes/BoilerplateGenerator.ts b/src/boilerplate/circuit/zokrates/nodes/BoilerplateGenerator.ts index 0254c5ad..5d2b4437 100644 --- a/src/boilerplate/circuit/zokrates/nodes/BoilerplateGenerator.ts +++ b/src/boilerplate/circuit/zokrates/nodes/BoilerplateGenerator.ts @@ -11,7 +11,7 @@ import MappingKey from '../../../../traverse/MappingKey.js'; const collectIncrements = (bpg: BoilerplateGenerator) => { const stateVarIndicator = bpg.thisIndicator || bpg.indicators; const incrementsArray: any[] = []; - let incrementsString = ''; + let incrementsString: string[] = []; if (stateVarIndicator.isStruct && ( stateVarIndicator instanceof StateVariableIndicator || @@ -27,7 +27,7 @@ const collectIncrements = (bpg: BoilerplateGenerator) => { bpg.thisIndicator = stateVarIndicator; } else { structIncs.incrementsArray[sp] = []; - structIncs.incrementsString[sp] = '0'; + structIncs.incrementsString[sp] = ['0']; } } return structIncs; @@ -35,6 +35,7 @@ const collectIncrements = (bpg: BoilerplateGenerator) => { // TODO sometimes decrements are added to .increments // current fix - prevent duplicates + let counter =-1; for (const inc of stateVarIndicator.increments) { if (inc.nodeType === 'IndexAccess') { const mappingKeyName = NodePath.getPath(inc).scope.getMappingKeyName(inc); @@ -53,12 +54,16 @@ const collectIncrements = (bpg: BoilerplateGenerator) => { precedingOperator: inc.precedingOperator, }); - if (inc === stateVarIndicator.increments[0]) { - incrementsString += `${modName}`; + if (counter != inc.counter) { + incrementsString[inc.counter] += `${modName}`; } else { - incrementsString += ` ${inc.precedingOperator} ${modName}`; + incrementsString[inc.counter] += ` ${inc.precedingOperator} ${modName}`; } + counter = inc.counter; } + let incCounter; + (counter === -1) ? incCounter = 0 : incCounter = counter +1; + counter = -1; for (const dec of stateVarIndicator.decrements) { if (dec.nodeType === 'IndexAccess') { const mappingKeyName = NodePath.getPath(dec).scope.getMappingKeyName(dec); @@ -78,13 +83,14 @@ const collectIncrements = (bpg: BoilerplateGenerator) => { precedingOperator: dec.precedingOperator, }); - if (!stateVarIndicator.decrements[1] && !stateVarIndicator.increments[0]) { - incrementsString += `${modName}`; + if (counter != dec.counter) { + incrementsString[dec.counter + incCounter] += `${modName}`; } else { // if we have decrements, this str represents the value we must take away // => it's a positive value with +'s - incrementsString += ` + ${modName}`; + incrementsString[dec.counter + incCounter] += `${dec.precedingOperator} ${modName}`; } + counter = dec.counter; } return { incrementsArray, incrementsString }; }; diff --git a/src/traverse/Indicator.ts b/src/traverse/Indicator.ts index 8486b6a1..25c91c82 100644 --- a/src/traverse/Indicator.ts +++ b/src/traverse/Indicator.ts @@ -633,10 +633,20 @@ export class StateVariableIndicator extends FunctionDefinitionIndicator { this.isDecremented ||= path.isDecremented; this.increments ??= []; this.decrements ??= []; + let incCounter =0; + if (this.increments[0] && state.increments[0]){ + incCounter = this.increments[this.increments.length -1].counter +1; + } state.increments.forEach((inc: any) => { + inc.counter = incCounter; this.increments?.push(inc); }); + let decCounter =0; + if (this.decrements[0] && state.decrements[0]){ + decCounter = this.decrements[this.decrements.length -1].counter +1; + } state.decrements.forEach((dec: any) => { + dec.counter = decCounter; this.decrements?.push(dec); }); if (this.isMapping) { From 32568d88b61d55236c2da3ef30280046adda3937 Mon Sep 17 00:00:00 2001 From: Lydia Garms Date: Fri, 5 Jul 2024 17:41:41 +0100 Subject: [PATCH 15/33] fix: multiple incrementations for some variable in circuit --- .../circuit/zokrates/nodes/BoilerplateGenerator.ts | 10 +++++----- .../circuit/zokrates/raw/BoilerplateGenerator.ts | 3 +-- src/codeGenerators/circuit/zokrates/toCircuit.ts | 7 +++++++ test/contracts/KnownUnknown.zol | 2 +- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/boilerplate/circuit/zokrates/nodes/BoilerplateGenerator.ts b/src/boilerplate/circuit/zokrates/nodes/BoilerplateGenerator.ts index 5d2b4437..3015fa7e 100644 --- a/src/boilerplate/circuit/zokrates/nodes/BoilerplateGenerator.ts +++ b/src/boilerplate/circuit/zokrates/nodes/BoilerplateGenerator.ts @@ -47,15 +47,15 @@ const collectIncrements = (bpg: BoilerplateGenerator) => { if (inc.nodeType === 'MemberAccess') inc.name ??= `${inc.expression.name}.${inc.memberName}`; if (!inc.name) inc.name = inc.value; let modName = inc.modName ? inc.modName : inc.name; - if (incrementsArray.some(existingInc => inc.name === existingInc.name)) + if (incrementsArray.some(existingInc => inc.name === existingInc.name && inc.id === existingInc.id)) continue; incrementsArray.push({ name: inc.name, precedingOperator: inc.precedingOperator, }); - - if (counter != inc.counter) { - incrementsString[inc.counter] += `${modName}`; + + if (counter !== inc.counter) { + incrementsString[inc.counter] = `${modName}`; } else { incrementsString[inc.counter] += ` ${inc.precedingOperator} ${modName}`; } @@ -84,7 +84,7 @@ const collectIncrements = (bpg: BoilerplateGenerator) => { }); if (counter != dec.counter) { - incrementsString[dec.counter + incCounter] += `${modName}`; + incrementsString[dec.counter + incCounter] = `${modName}`; } else { // if we have decrements, this str represents the value we must take away // => it's a positive value with +'s diff --git a/src/boilerplate/circuit/zokrates/raw/BoilerplateGenerator.ts b/src/boilerplate/circuit/zokrates/raw/BoilerplateGenerator.ts index cdd792a1..facea931 100644 --- a/src/boilerplate/circuit/zokrates/raw/BoilerplateGenerator.ts +++ b/src/boilerplate/circuit/zokrates/raw/BoilerplateGenerator.ts @@ -529,10 +529,9 @@ class BoilerplateGenerator { importStatements(): string[] { return []; // TODO: we might eventually import some underflow/overflow functions. }, - statements({ name: x, addend, newCommitmentValue, structProperties, memberName}): string[] { if (structProperties) { - return [`${x}.${memberName} = ${x}.${memberName} + ${newCommitmentValue[memberName]}`] + return [`${x}.${memberName} = ${x}.${memberName} + ${newCommitmentValue}`] } return [`${x} = ${x} + ${newCommitmentValue}`]; //return [ diff --git a/src/codeGenerators/circuit/zokrates/toCircuit.ts b/src/codeGenerators/circuit/zokrates/toCircuit.ts index 8c92ee05..f93b0695 100644 --- a/src/codeGenerators/circuit/zokrates/toCircuit.ts +++ b/src/codeGenerators/circuit/zokrates/toCircuit.ts @@ -312,6 +312,13 @@ function codeGenerator(node: any) { return Circuitbp.generateBoilerplate(node); case 'BoilerplateStatement': { + let newComValue = ''; + if (node.bpType === 'incrementation') newComValue = codeGenerator(node.addend); + if (node.bpType === 'decrementation') newComValue = codeGenerator(node.subtrahend); + console.log(node.newCommitmentValue); + console.log(node.addend); + console.log(newComValue); + node.newCommitmentValue = newComValue; return Circuitbp.generateBoilerplate(node); } diff --git a/test/contracts/KnownUnknown.zol b/test/contracts/KnownUnknown.zol index 0f30df65..512d217f 100644 --- a/test/contracts/KnownUnknown.zol +++ b/test/contracts/KnownUnknown.zol @@ -17,7 +17,7 @@ contract Assign { unknown x.prop1 += value + a; unknown x.prop2 += value; unknown b += value; - unknown x.prop1 += value ; + unknown x.prop1 += value; a+= value; } From f3938113acb7d9824c5e48df7d45e96103add43c Mon Sep 17 00:00:00 2001 From: Lydia Garms Date: Fri, 5 Jul 2024 17:46:58 +0100 Subject: [PATCH 16/33] fix: for decrementation --- src/boilerplate/circuit/zokrates/raw/BoilerplateGenerator.ts | 2 +- src/codeGenerators/circuit/zokrates/toCircuit.ts | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/boilerplate/circuit/zokrates/raw/BoilerplateGenerator.ts b/src/boilerplate/circuit/zokrates/raw/BoilerplateGenerator.ts index facea931..b5fbc3cf 100644 --- a/src/boilerplate/circuit/zokrates/raw/BoilerplateGenerator.ts +++ b/src/boilerplate/circuit/zokrates/raw/BoilerplateGenerator.ts @@ -549,7 +549,7 @@ class BoilerplateGenerator { statements({ name: x, subtrahend, newCommitmentValue, structProperties, memberName}): string[] { if (structProperties) { - return [`${x}.${memberName} = ${x}.${memberName} - ${newCommitmentValue[memberName]}`] + return [`${x}.${memberName} = ${x}.${memberName} - ${newCommitmentValue}`] } return [`${x} = ${x} - (${newCommitmentValue})`]; // const y = codeGenerator(subtrahend); diff --git a/src/codeGenerators/circuit/zokrates/toCircuit.ts b/src/codeGenerators/circuit/zokrates/toCircuit.ts index f93b0695..07378bc0 100644 --- a/src/codeGenerators/circuit/zokrates/toCircuit.ts +++ b/src/codeGenerators/circuit/zokrates/toCircuit.ts @@ -315,9 +315,6 @@ function codeGenerator(node: any) { let newComValue = ''; if (node.bpType === 'incrementation') newComValue = codeGenerator(node.addend); if (node.bpType === 'decrementation') newComValue = codeGenerator(node.subtrahend); - console.log(node.newCommitmentValue); - console.log(node.addend); - console.log(newComValue); node.newCommitmentValue = newComValue; return Circuitbp.generateBoilerplate(node); } From 7973409d5ca0267070c2d622178434f65fc03b4f Mon Sep 17 00:00:00 2001 From: Lydia Garms Date: Fri, 5 Jul 2024 18:05:48 +0100 Subject: [PATCH 17/33] fix: missing brackets --- src/boilerplate/circuit/zokrates/raw/BoilerplateGenerator.ts | 2 +- test/contracts/KnownUnknown.zol | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/boilerplate/circuit/zokrates/raw/BoilerplateGenerator.ts b/src/boilerplate/circuit/zokrates/raw/BoilerplateGenerator.ts index b5fbc3cf..d4da9a91 100644 --- a/src/boilerplate/circuit/zokrates/raw/BoilerplateGenerator.ts +++ b/src/boilerplate/circuit/zokrates/raw/BoilerplateGenerator.ts @@ -549,7 +549,7 @@ class BoilerplateGenerator { statements({ name: x, subtrahend, newCommitmentValue, structProperties, memberName}): string[] { if (structProperties) { - return [`${x}.${memberName} = ${x}.${memberName} - ${newCommitmentValue}`] + return [`${x}.${memberName} = ${x}.${memberName} - (${newCommitmentValue})`] } return [`${x} = ${x} - (${newCommitmentValue})`]; // const y = codeGenerator(subtrahend); diff --git a/test/contracts/KnownUnknown.zol b/test/contracts/KnownUnknown.zol index 512d217f..8f399cec 100644 --- a/test/contracts/KnownUnknown.zol +++ b/test/contracts/KnownUnknown.zol @@ -25,6 +25,8 @@ contract Assign { unknown b -= value +a; unknown x.prop1 -= value + a; unknown x.prop2 -= value; + unknown b -= value; + unknown x.prop1 -= value; a+= value; } From 68fe11c3454ac75f1cdb179880068eec90832481 Mon Sep 17 00:00:00 2001 From: Lydia Garms Date: Mon, 8 Jul 2024 11:03:15 +0100 Subject: [PATCH 18/33] fix: msgSender appearing as msg in Buckets of Balls and causing a circuit compilation error --- .../circuit/zokrates/nodes/BoilerplateGenerator.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/boilerplate/circuit/zokrates/nodes/BoilerplateGenerator.ts b/src/boilerplate/circuit/zokrates/nodes/BoilerplateGenerator.ts index 3015fa7e..bdd93925 100644 --- a/src/boilerplate/circuit/zokrates/nodes/BoilerplateGenerator.ts +++ b/src/boilerplate/circuit/zokrates/nodes/BoilerplateGenerator.ts @@ -227,8 +227,10 @@ class BoilerplateGenerator { this.assignIndicators(mappingKeyIndicator); this.mappingKeyName = mappingKeyName.replace('[', '_').replace(']', ''); if (this.mappingKeyName.split('.').length > 2) this.mappingKeyName.replace('.', 'dot'); + if(this.mappingKeyName == 'msg') + this.mappingKeyName = this.mappingKeyName+mappingKeyIndicator.keyPath.parent.memberName.replace('sender','Sender').replace('value','Value'); this.mappingName = this.indicators.name; - this.name = `${this.mappingName}_${mappingKeyName}`.replaceAll('.', 'dot').replace('[', '_').replace(']', ''); + this.name = `${this.mappingName}_${this.mappingKeyName}`.replaceAll('.', 'dot').replace('[', '_').replace(']', ''); } generateBoilerplateStatement(bpType: string, extraParams?: any) { @@ -237,7 +239,6 @@ class BoilerplateGenerator { const { mappingKeyName } = extraParams; this.refresh(mappingKeyName); } - this.initialise(this.indicators); return { nodeType: 'BoilerplateStatement', bpSection: 'statements', From 1f65c4c847cc8928279751b3ec53d18e5879f39e Mon Sep 17 00:00:00 2001 From: Lydia Garms Date: Mon, 8 Jul 2024 11:57:27 +0100 Subject: [PATCH 19/33] fix: _ instead of . in circuit causing compilation error for SimpleStruct2 and for incremented non-structs alllow for multiple incrementations --- src/boilerplate/circuit/zokrates/raw/BoilerplateGenerator.ts | 2 +- .../orchestration/javascript/raw/boilerplate-generator.ts | 4 +++- src/codeGenerators/orchestration/nodejs/toOrchestration.ts | 5 +++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/boilerplate/circuit/zokrates/raw/BoilerplateGenerator.ts b/src/boilerplate/circuit/zokrates/raw/BoilerplateGenerator.ts index d4da9a91..a47ff293 100644 --- a/src/boilerplate/circuit/zokrates/raw/BoilerplateGenerator.ts +++ b/src/boilerplate/circuit/zokrates/raw/BoilerplateGenerator.ts @@ -376,7 +376,7 @@ class BoilerplateGenerator { } else { - lines.push(`${typeName} ${x}_newCommitment_value = ${typeName} { ${structProperties.map(p => ` ${p}: ${isWhole ? `${y}.${p}` : `${y}_${p}`}`)} }\n`); + lines.push(`${typeName} ${x}_newCommitment_value = ${typeName} { ${structProperties.map(p => ` ${p}: ${y}.${p}`)} }\n`); if (structPropertiesTypes) { structPropertiesTypes.forEach(property => { if (property.typeName === 'bool'){ diff --git a/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts b/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts index 66c25cad..52b28fb5 100644 --- a/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts +++ b/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts @@ -119,7 +119,9 @@ class BoilerplateGenerator { \n\n// read preimage for incremented state ${stateName}_newOwnerPublicKey = ${newOwnerStatment} ${stateVarIds.join('\n')} - \n`]; + \n + let ${stateName}_newCommitmentValue = generalise(0); + `]; case 'decrement': if (structProperties) return [` diff --git a/src/codeGenerators/orchestration/nodejs/toOrchestration.ts b/src/codeGenerators/orchestration/nodejs/toOrchestration.ts index 78dadfc3..39f83510 100644 --- a/src/codeGenerators/orchestration/nodejs/toOrchestration.ts +++ b/src/codeGenerators/orchestration/nodejs/toOrchestration.ts @@ -126,13 +126,14 @@ export default function codeGenerator(node: any, options: any = {}): any { if (node.incrementsSecretState && (node.interactsWithSecret || node.expression?.internalFunctionInteractsWithSecret)){ let privateStateName = node.privateStateName.replace(/\./g, '_'); + let increments = codeGenerator(node.expression.rightHandSide); if (typeof node.increments === 'object' && node.increments !== null) { if (node.expression.leftHandSide.nodeType === 'MemberAccess'){ let propName = node.expression.leftHandSide.memberName; - return `\nconst ${privateStateName}_newCommitmentValue = generalise(${node.increments[propName]});\n`; + return `\n${privateStateName}_newCommitmentValue = generalise(${node.increments[propName]});\n`; } }; - return `\nconst ${privateStateName}_newCommitmentValue = generalise(${node.increments});\n`; + return `\n${privateStateName}_newCommitmentValue = generalise(parseInt(${privateStateName}_newCommitmentValue.integer, 10) + ${increments});\n`; } if (!node.interactsWithSecret) From f2be420ead68855b0c680f2687edd9b6204af9a9 Mon Sep 17 00:00:00 2001 From: Lydia Garms Date: Mon, 8 Jul 2024 13:44:55 +0100 Subject: [PATCH 20/33] fix: allow for multiple increments for structs --- .../javascript/raw/boilerplate-generator.ts | 1 + .../orchestration/nodejs/toOrchestration.ts | 18 ++++++++++-------- test/contracts/KnownUnknown.zol | 4 ++-- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts b/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts index 52b28fb5..507b2a9e 100644 --- a/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts +++ b/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts @@ -114,6 +114,7 @@ class BoilerplateGenerator { ${stateName}_newOwnerPublicKey = ${newOwnerStatment} ${stateVarIds.join('\n')} \n + ${structProperties.map(sp => `let ${stateName}_${sp}_newCommitmentValue = generalise(0);\n`).join('')} `]; return [` \n\n// read preimage for incremented state diff --git a/src/codeGenerators/orchestration/nodejs/toOrchestration.ts b/src/codeGenerators/orchestration/nodejs/toOrchestration.ts index 39f83510..6d163a2a 100644 --- a/src/codeGenerators/orchestration/nodejs/toOrchestration.ts +++ b/src/codeGenerators/orchestration/nodejs/toOrchestration.ts @@ -126,14 +126,16 @@ export default function codeGenerator(node: any, options: any = {}): any { if (node.incrementsSecretState && (node.interactsWithSecret || node.expression?.internalFunctionInteractsWithSecret)){ let privateStateName = node.privateStateName.replace(/\./g, '_'); - let increments = codeGenerator(node.expression.rightHandSide); - if (typeof node.increments === 'object' && node.increments !== null) { - if (node.expression.leftHandSide.nodeType === 'MemberAccess'){ - let propName = node.expression.leftHandSide.memberName; - return `\n${privateStateName}_newCommitmentValue = generalise(${node.increments[propName]});\n`; - } - }; - return `\n${privateStateName}_newCommitmentValue = generalise(parseInt(${privateStateName}_newCommitmentValue.integer, 10) + ${increments});\n`; + let increments; + if (node.expression.operator === '+='){ + increments = codeGenerator(node.expression.rightHandSide); + return `\n${privateStateName}_newCommitmentValue = generalise(parseInt(${privateStateName}_newCommitmentValue.integer, 10) + ${increments});\n`; + } + if (node.expression.operator === '='){ + increments = codeGenerator(node.expression.rightHandSide); + increments = increments.replace(new RegExp(privateStateName, 'g'), `${privateStateName}_newCommitmentValue`); + return `\n${privateStateName}_newCommitmentValue = generalise(${increments});\n`; + } } if (!node.interactsWithSecret) diff --git a/test/contracts/KnownUnknown.zol b/test/contracts/KnownUnknown.zol index 8f399cec..65975229 100644 --- a/test/contracts/KnownUnknown.zol +++ b/test/contracts/KnownUnknown.zol @@ -13,11 +13,11 @@ contract Assign { function add( uint256 value ) public { - unknown b += value +a; + unknown b = b + value +a; unknown x.prop1 += value + a; unknown x.prop2 += value; unknown b += value; - unknown x.prop1 += value; + unknown x.prop1 += a; a+= value; } From 1eda67fabb44f59a6e15a4dba73a1955c45d5ca8 Mon Sep 17 00:00:00 2001 From: Lydia Garms Date: Mon, 8 Jul 2024 15:02:43 +0100 Subject: [PATCH 21/33] fix: multiple incrementations for decrements in orchestration --- .../orchestration/javascript/raw/boilerplate-generator.ts | 4 +++- .../orchestration/nodejs/toOrchestration.ts | 8 ++++++++ test/contracts/KnownUnknown.zol | 3 ++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts b/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts index 507b2a9e..9a4df382 100644 --- a/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts +++ b/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts @@ -131,13 +131,15 @@ class BoilerplateGenerator { ${stateVarIds.join('\n')} \nlet ${stateName}_preimage = await getCommitmentsById(${stateName}_stateVarId); \n + ${structProperties.map(sp => `let ${stateName}_${sp}_newCommitmentValue = generalise(0);\n`).join('')} `]; return [` \n\n// read preimage for decremented state \n${stateName}_newOwnerPublicKey = ${newOwnerStatment} ${stateVarIds.join('\n')} \nlet ${stateName}_preimage = await getCommitmentsById(${stateName}_stateVarId); - \n` ]; + \n + let ${stateName}_newCommitmentValue = generalise(0);` ]; case 'whole': switch (reinitialisedOnly) { case true: diff --git a/src/codeGenerators/orchestration/nodejs/toOrchestration.ts b/src/codeGenerators/orchestration/nodejs/toOrchestration.ts index 6d163a2a..92735f5f 100644 --- a/src/codeGenerators/orchestration/nodejs/toOrchestration.ts +++ b/src/codeGenerators/orchestration/nodejs/toOrchestration.ts @@ -131,8 +131,16 @@ export default function codeGenerator(node: any, options: any = {}): any { increments = codeGenerator(node.expression.rightHandSide); return `\n${privateStateName}_newCommitmentValue = generalise(parseInt(${privateStateName}_newCommitmentValue.integer, 10) + ${increments});\n`; } + if (node.expression.operator === '-='){ + increments = codeGenerator(node.expression.rightHandSide); + return `\n${privateStateName}_newCommitmentValue = generalise(parseInt(${privateStateName}_newCommitmentValue.integer, 10) + (${increments}));\n`; + } if (node.expression.operator === '='){ increments = codeGenerator(node.expression.rightHandSide); + if (node.decrementsSecretState){ + increments = increments.replace(new RegExp(`${privateStateName}.integer`, 'g'), `0`); + return `\n${privateStateName}_newCommitmentValue = generalise(parseInt(${privateStateName}_newCommitmentValue.integer, 10) - (${increments}));\n`; + } increments = increments.replace(new RegExp(privateStateName, 'g'), `${privateStateName}_newCommitmentValue`); return `\n${privateStateName}_newCommitmentValue = generalise(${increments});\n`; } diff --git a/test/contracts/KnownUnknown.zol b/test/contracts/KnownUnknown.zol index 65975229..aee281a8 100644 --- a/test/contracts/KnownUnknown.zol +++ b/test/contracts/KnownUnknown.zol @@ -22,7 +22,8 @@ contract Assign { } function remove( uint256 value ) public { - unknown b -= value +a; + unknown b = b - value +a; + unknown b = b - (value +a); unknown x.prop1 -= value + a; unknown x.prop2 -= value; unknown b -= value; From 93d47fdf7abe6d31d6bebde341c6382f58c4d6e8 Mon Sep 17 00:00:00 2001 From: Lydia Garms Date: Mon, 8 Jul 2024 17:38:17 +0100 Subject: [PATCH 22/33] chore: mark accessed unknown variables as unsupported - specifically variables on the rhs --- src/transformers/visitors/checks/accessedVisitor.ts | 9 +++++++++ test/contracts/KnownUnknown.zol | 1 + 2 files changed, 10 insertions(+) diff --git a/src/transformers/visitors/checks/accessedVisitor.ts b/src/transformers/visitors/checks/accessedVisitor.ts index 56d95fc1..09d58f14 100644 --- a/src/transformers/visitors/checks/accessedVisitor.ts +++ b/src/transformers/visitors/checks/accessedVisitor.ts @@ -151,6 +151,15 @@ export default { node.accessedSecretState = true; return; } + // We need to ouput an error if a partitioned state is being accessed. + //This seems difficult to support because we need the sum of the value of every commitment, how do we enforce that the prover inputs every commitment to the circuit? + else if (rightAncestor){ + const indicator = scope.getReferencedIndicator(node); + if (indicator instanceof StateVariableIndicator) throw new TODOError( + `A partitioned state variable cannot be accessed`, + node, + ); + } // below: check if the identifier is on the LHS and is NOT partitioned AND requires the LHS value e.g. a *= b // we don't check all the types of LHS container, because a +=,*=,-= b is always an Assignment with a .leftHandSide const leftAncestor = path.getAncestorContainedWithin('leftHandSide'); diff --git a/test/contracts/KnownUnknown.zol b/test/contracts/KnownUnknown.zol index aee281a8..c88d2f9a 100644 --- a/test/contracts/KnownUnknown.zol +++ b/test/contracts/KnownUnknown.zol @@ -19,6 +19,7 @@ contract Assign { unknown b += value; unknown x.prop1 += a; a+= value; + //unknown b -= value; } function remove( uint256 value ) public { From f97e073cfa2789e4ad8984471f2a1cab5f8ebe3b Mon Sep 17 00:00:00 2001 From: Lydia Garms Date: Mon, 8 Jul 2024 18:03:18 +0100 Subject: [PATCH 23/33] fix: test contract --- src/transformers/visitors/checks/accessedVisitor.ts | 2 +- test/contracts/KnownUnknown.zol | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/transformers/visitors/checks/accessedVisitor.ts b/src/transformers/visitors/checks/accessedVisitor.ts index 09d58f14..7153c59b 100644 --- a/src/transformers/visitors/checks/accessedVisitor.ts +++ b/src/transformers/visitors/checks/accessedVisitor.ts @@ -156,7 +156,7 @@ export default { else if (rightAncestor){ const indicator = scope.getReferencedIndicator(node); if (indicator instanceof StateVariableIndicator) throw new TODOError( - `A partitioned state variable cannot be accessed`, + `A partitioned state variable cannot be accessed. Only incrementations/ decrementations of form +=, -= are allowed.`, node, ); } diff --git a/test/contracts/KnownUnknown.zol b/test/contracts/KnownUnknown.zol index c88d2f9a..9cff8861 100644 --- a/test/contracts/KnownUnknown.zol +++ b/test/contracts/KnownUnknown.zol @@ -13,7 +13,8 @@ contract Assign { function add( uint256 value ) public { - unknown b = b + value +a; + //unknown b = b + value +a; + unknown b += value +a; unknown x.prop1 += value + a; unknown x.prop2 += value; unknown b += value; @@ -23,8 +24,9 @@ contract Assign { } function remove( uint256 value ) public { - unknown b = b - value +a; - unknown b = b - (value +a); + //unknown b = b - value +a; + unknown b -= value +a; + //unknown b = b - (value +a); unknown x.prop1 -= value + a; unknown x.prop2 -= value; unknown b -= value; From 33c2e099cf8baf9edb3ad8961a2972bfd6895b40 Mon Sep 17 00:00:00 2001 From: Lydia Garms Date: Wed, 24 Jul 2024 18:17:44 +0100 Subject: [PATCH 24/33] fix: error checks for unknown variables --- .../visitors/checks/accessedVisitor.ts | 8 ++++++-- .../visitors/checks/incrementedVisitor.ts | 15 +++++++-------- test/contracts/Assign-type-conversion.zol | 2 +- test/contracts/KnownUnknown.zol | 7 ++----- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/transformers/visitors/checks/accessedVisitor.ts b/src/transformers/visitors/checks/accessedVisitor.ts index 7153c59b..6c744ae2 100644 --- a/src/transformers/visitors/checks/accessedVisitor.ts +++ b/src/transformers/visitors/checks/accessedVisitor.ts @@ -91,6 +91,7 @@ export default { if (indicator instanceof StateVariableIndicator) indicator.updateAccessed(path); return; } + // if this state is on the rhs AND isn't incremented OR is in an incrementation, but its not being incremented: if ( rightAncestor && @@ -153,10 +154,13 @@ export default { } // We need to ouput an error if a partitioned state is being accessed. //This seems difficult to support because we need the sum of the value of every commitment, how do we enforce that the prover inputs every commitment to the circuit? - else if (rightAncestor){ + else if (rightAncestor && + referencedBinding.isPartitioned + && (lhsNode.name !== node.name || !state.inIncrementation) + ){ const indicator = scope.getReferencedIndicator(node); if (indicator instanceof StateVariableIndicator) throw new TODOError( - `A partitioned state variable cannot be accessed. Only incrementations/ decrementations of form +=, -= are allowed.`, + `A partitioned state variable cannot be accessed. Only incrementations/ decrementations such as +=, -= are allowed.`, node, ); } diff --git a/src/transformers/visitors/checks/incrementedVisitor.ts b/src/transformers/visitors/checks/incrementedVisitor.ts index e4bba3ab..90c02dc1 100644 --- a/src/transformers/visitors/checks/incrementedVisitor.ts +++ b/src/transformers/visitors/checks/incrementedVisitor.ts @@ -435,9 +435,9 @@ export default { if ( nameMatch && precedingOperator[index + 1]?.includes('+') && // we have ... + a + ... - precedingOperator[index]?.includes('+') // otherwise we have a = b - a + (index ===0) + //precedingOperator[index]?.includes('+') // otherwise we have a = b - a ) { - discoveredLHS += 1; isIncremented = { incremented: true, decremented: false }; } @@ -445,17 +445,16 @@ export default { if ( nameMatch && precedingOperator[index + 1]?.includes('-') && // we have ... + a - ... - precedingOperator[index]?.includes('+') // otherwise we have a = b - a + (index ===0) + //precedingOperator[index]?.includes('+') // otherwise we have a = b - a ) { - discoveredLHS += 1; isIncremented = { incremented: true, decremented: true }; } - // a = something - a + if ( - nameMatch && - precedingOperator[index]?.includes('-') // we have a = b - a + nameMatch ) { - discoveredLHS -= 1; + discoveredLHS += 1; } // if none, go to the next operand if (operand.indexExpression?.expression?.name === 'msg') diff --git a/test/contracts/Assign-type-conversion.zol b/test/contracts/Assign-type-conversion.zol index 7c609e95..4ca3c539 100644 --- a/test/contracts/Assign-type-conversion.zol +++ b/test/contracts/Assign-type-conversion.zol @@ -13,6 +13,6 @@ contract Assign { } function remove(uint256 remval) public { - b -= uint(uint128(remval)); + b += uint(uint128(remval)); } } diff --git a/test/contracts/KnownUnknown.zol b/test/contracts/KnownUnknown.zol index 9cff8861..2998a513 100644 --- a/test/contracts/KnownUnknown.zol +++ b/test/contracts/KnownUnknown.zol @@ -13,8 +13,7 @@ contract Assign { function add( uint256 value ) public { - //unknown b = b + value +a; - unknown b += value +a; + unknown b = b + value +a; unknown x.prop1 += value + a; unknown x.prop2 += value; unknown b += value; @@ -24,9 +23,7 @@ contract Assign { } function remove( uint256 value ) public { - //unknown b = b - value +a; - unknown b -= value +a; - //unknown b = b - (value +a); + unknown b = b - (value +a); unknown x.prop1 -= value + a; unknown x.prop2 -= value; unknown b -= value; From e37c648745c9c25212c67f1cafe4453daaf272b0 Mon Sep 17 00:00:00 2001 From: Lydia Garms Date: Thu, 25 Jul 2024 09:55:46 +0100 Subject: [PATCH 25/33] fix: error in operands array --- src/transformers/visitors/checks/incrementedVisitor.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/transformers/visitors/checks/incrementedVisitor.ts b/src/transformers/visitors/checks/incrementedVisitor.ts index 90c02dc1..1d1fdea4 100644 --- a/src/transformers/visitors/checks/incrementedVisitor.ts +++ b/src/transformers/visitors/checks/incrementedVisitor.ts @@ -155,7 +155,8 @@ const binOpToIncrements = (path: NodePath, state: any) => { precedingOperator.splice(2, 0, operand.operator); } } - operands.splice(0, 0, operands[operands.length -1]).slice(0, -1); + operands.splice(0, 0, operands[operands.length -1]); + operands.pop(); } // fills an array of operands @@ -170,8 +171,8 @@ const binOpToIncrements = (path: NodePath, state: any) => { } } operands.splice(0, 0, operands[operands.length -1]); + operands.pop(); } - // if we have mixed operators, we may have an underflow or not be able to tell whether this is increasing (incrementation) or decreasing (decrementation) the secret value // Here we give out a warning when we don't use parentheses. if ( @@ -187,6 +188,7 @@ const binOpToIncrements = (path: NodePath, state: any) => { `Whenever you have multiple operands in an expression, such as a = a - b - c + d, it's better to use parentheses for clarity. For example, rewrite it as a = a - (b + c - d). This makes the expression easier to understand. `, ); } + if(assignmentOp === '=' && precedingOperator.length > 2) { if(isTupleExpression) { operands.splice(0, 0, path.node.leftExpression); From 15b561afdbe272024a15866a499fc222336104b6 Mon Sep 17 00:00:00 2001 From: Lydia Garms Date: Thu, 25 Jul 2024 13:18:59 +0100 Subject: [PATCH 26/33] fix: bug due to state being set as path causing incrementations to be marked incorrectly --- .../visitors/checks/accessedVisitor.ts | 18 +++--------------- test/error-checks/KnownUnknown3.zol | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 15 deletions(-) create mode 100644 test/error-checks/KnownUnknown3.zol diff --git a/src/transformers/visitors/checks/accessedVisitor.ts b/src/transformers/visitors/checks/accessedVisitor.ts index 6c744ae2..80bf7d82 100644 --- a/src/transformers/visitors/checks/accessedVisitor.ts +++ b/src/transformers/visitors/checks/accessedVisitor.ts @@ -26,7 +26,8 @@ export default { state.incrementedDeclaration = path.incrementedDeclaration; } }, - exit(state: any) { + // path is unused here but if unincluded we cannot acccess the state object + exit(path: NodePath, state: any) { state.inIncrementation = false; state.incrementedDeclaration = null; }, @@ -41,7 +42,7 @@ export default { // e.g. a = a + b --> b accessed // e.g. a += 10, a whole --> a accessed // e.g. myMapping[a] = x --> a accessed - const { node, scope } = path; + const { node, scope} = path; if (path.isMsg()) return; // the node represents the special 'msg' type in solidity if (path.isThis()) return; // the node represents the special 'this' type in solidity if (path.isExportedSymbol()) return; // the node represents an external contract name @@ -91,7 +92,6 @@ export default { if (indicator instanceof StateVariableIndicator) indicator.updateAccessed(path); return; } - // if this state is on the rhs AND isn't incremented OR is in an incrementation, but its not being incremented: if ( rightAncestor && @@ -152,18 +152,6 @@ export default { node.accessedSecretState = true; return; } - // We need to ouput an error if a partitioned state is being accessed. - //This seems difficult to support because we need the sum of the value of every commitment, how do we enforce that the prover inputs every commitment to the circuit? - else if (rightAncestor && - referencedBinding.isPartitioned - && (lhsNode.name !== node.name || !state.inIncrementation) - ){ - const indicator = scope.getReferencedIndicator(node); - if (indicator instanceof StateVariableIndicator) throw new TODOError( - `A partitioned state variable cannot be accessed. Only incrementations/ decrementations such as +=, -= are allowed.`, - node, - ); - } // below: check if the identifier is on the LHS and is NOT partitioned AND requires the LHS value e.g. a *= b // we don't check all the types of LHS container, because a +=,*=,-= b is always an Assignment with a .leftHandSide const leftAncestor = path.getAncestorContainedWithin('leftHandSide'); diff --git a/test/error-checks/KnownUnknown3.zol b/test/error-checks/KnownUnknown3.zol new file mode 100644 index 00000000..db1c3721 --- /dev/null +++ b/test/error-checks/KnownUnknown3.zol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: CC0 +pragma solidity ^0.8.0; +contract Assign { + secret uint256 private a; + secret uint256 private b; + + + function add( uint256 value ) public { + unknown b += value +a; + a+= b + value; + //a = a + b + value; + //a = b + value; + } + + +} \ No newline at end of file From de161ec055c77ca9737e0e8f83610c4d31da9aef Mon Sep 17 00:00:00 2001 From: Lydia Garms Date: Fri, 26 Jul 2024 12:28:39 +0100 Subject: [PATCH 27/33] fix: errors due to += expanded twice in circuit and undefined added as a proof input in orchestration --- .../zokrates/raw/BoilerplateGenerator.ts | 27 +++++++++++---- .../javascript/raw/toOrchestration.ts | 12 ++++--- .../circuit/zokrates/toCircuit.ts | 1 - .../orchestration/nodejs/toOrchestration.ts | 1 - src/transformers/visitors/toCircuitVisitor.ts | 3 +- .../visitors/toOrchestrationVisitor.ts | 2 +- test/contracts/KnownUnknown.zol | 14 +++++++- test/contracts/KnownUnknown1.zol | 34 +++++++++++++++++++ 8 files changed, 78 insertions(+), 16 deletions(-) create mode 100644 test/contracts/KnownUnknown1.zol diff --git a/src/boilerplate/circuit/zokrates/raw/BoilerplateGenerator.ts b/src/boilerplate/circuit/zokrates/raw/BoilerplateGenerator.ts index a47ff293..7253a0f9 100644 --- a/src/boilerplate/circuit/zokrates/raw/BoilerplateGenerator.ts +++ b/src/boilerplate/circuit/zokrates/raw/BoilerplateGenerator.ts @@ -530,10 +530,17 @@ class BoilerplateGenerator { return []; // TODO: we might eventually import some underflow/overflow functions. }, statements({ name: x, addend, newCommitmentValue, structProperties, memberName}): string[] { - if (structProperties) { - return [`${x}.${memberName} = ${x}.${memberName} + ${newCommitmentValue}`] + if (addend.incrementType === '+='){ + if (structProperties) { + return [`${x}.${memberName} = ${x}.${memberName} + ${newCommitmentValue}`] + } + return [`${x} = ${x} + ${newCommitmentValue}`]; + } else if (addend.incrementType === '='){ + if (structProperties) { + return [`${x}.${memberName} = ${newCommitmentValue}`] + } + return [`${x} = ${newCommitmentValue}`]; } - return [`${x} = ${x} + ${newCommitmentValue}`]; //return [ // `// Skipping incrementation of ${x}` // ` @@ -548,10 +555,18 @@ class BoilerplateGenerator { }, statements({ name: x, subtrahend, newCommitmentValue, structProperties, memberName}): string[] { - if (structProperties) { - return [`${x}.${memberName} = ${x}.${memberName} - (${newCommitmentValue})`] + if (subtrahend.decrementType === '-='){ + if (structProperties) { + return [`${x}.${memberName} = ${x}.${memberName} - (${newCommitmentValue})`] + } + return [`${x} = ${x} - (${newCommitmentValue})`]; + } else if (subtrahend.decrementType === '='){ + if (structProperties) { + return [`${x}.${memberName} = ${newCommitmentValue}`] + } + return [`${x} = ${newCommitmentValue}`]; } - return [`${x} = ${x} - (${newCommitmentValue})`]; + // const y = codeGenerator(subtrahend); // let i = startIndex; // const x0 = `${x}_${i++}`; diff --git a/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts b/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts index da589d52..35f498e9 100644 --- a/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts +++ b/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts @@ -205,16 +205,17 @@ export const generateProofBoilerplate = (node: any) => { case true: // decrement if (stateNode.structProperties) stateNode.increment = Object.values(stateNode.increment).flat(Infinity); - stateNode.increment.forEach((inc: any) => { + // Below has been removed as it does not appear to be needed. Revisit if issues arise. + /*stateNode.increment.forEach((inc: any) => { // +inc.name tries to convert into a number - we don't want to add constants here if ( !output.join().includes(`\t${inc.name}.integer`) && !parameters.includes(`\t${inc.name}.integer,`) && !privateStateNames.includes(inc.name) && !inc.accessed && - !+inc.name + !+inc.name && inc.name ) output.push(`\n\t\t\t\t\t\t\t\t${inc.name}.integer`); - }); + });*/ output.push( Orchestrationbp.generateProof.parameters({ stateName, @@ -241,14 +242,15 @@ export const generateProofBoilerplate = (node: any) => { default: // increment if (stateNode.structProperties) stateNode.increment = Object.values(stateNode.increment).flat(Infinity); - stateNode.increment.forEach((inc: any) => { + // Below has been removed as it does not appear to be needed. Revisit if issues arise. + /*stateNode.increment.forEach((inc: any) => { if ( !output.join().includes(`\t${inc.name}.integer`) && !parameters.includes(`\t${inc.name}.integer,`) && !inc.accessed && !+inc.name ) output.push(`\n\t\t\t\t\t\t\t\t${inc.name}.integer`); - }); + });*/ output.push( Orchestrationbp.generateProof.parameters( { stateName, diff --git a/src/codeGenerators/circuit/zokrates/toCircuit.ts b/src/codeGenerators/circuit/zokrates/toCircuit.ts index 8e02fdea..62667eaa 100644 --- a/src/codeGenerators/circuit/zokrates/toCircuit.ts +++ b/src/codeGenerators/circuit/zokrates/toCircuit.ts @@ -91,7 +91,6 @@ function codeGenerator(node: any) { } }); } - functionSignature = `def main(\\\n\t${codeGenerator(node.parameters)}\\\n) -> `; node.returnParameters.parameters.forEach((node) => { if((node.isPrivate === true && node.typeName.name != 'bool') || node.typeName.name.includes('EncryptedMsgs')) diff --git a/src/codeGenerators/orchestration/nodejs/toOrchestration.ts b/src/codeGenerators/orchestration/nodejs/toOrchestration.ts index 0ff87d0e..76af2e34 100644 --- a/src/codeGenerators/orchestration/nodejs/toOrchestration.ts +++ b/src/codeGenerators/orchestration/nodejs/toOrchestration.ts @@ -128,7 +128,6 @@ export default function codeGenerator(node: any, options: any = {}): any { if (!node.incrementsSecretState && (node.interactsWithSecret || node.expression?.internalFunctionInteractsWithSecret)){ return `\n${codeGenerator(node.expression)};`; } - if (node.incrementsSecretState && (node.interactsWithSecret || node.expression?.internalFunctionInteractsWithSecret)){ let privateStateName = node.privateStateName.replace(/\./g, '_'); let increments; diff --git a/src/transformers/visitors/toCircuitVisitor.ts b/src/transformers/visitors/toCircuitVisitor.ts index 300833ff..db99291a 100644 --- a/src/transformers/visitors/toCircuitVisitor.ts +++ b/src/transformers/visitors/toCircuitVisitor.ts @@ -931,7 +931,6 @@ const visitor = { } // The child of this 'ExpressionStatement' node is an 'Assignment' node. But we've built a newNode to replace the 'Assignment' node of the original tree. The child of this newNode will be the RHS of the original 'Assignment' node. We discard the LHS, so we need to 'skip' the traversal of the 'Assignment' (using skipSubNodes = true), and instead traverse directly into the RHS node. - tempRHSParent._newASTPointer = newNode; // we don't want to add public inputs twice: @@ -946,6 +945,8 @@ const visitor = { state.skipSubNodes = true; parent._newASTPointer.push(newNode); incrementNames(newNode, lhsIndicator); + if (newNode.addend) newNode.addend.incrementType = expression.operator; + if (newNode.subtrahend) newNode.subtrahend.decrementType = expression.operator; return; } default: diff --git a/src/transformers/visitors/toOrchestrationVisitor.ts b/src/transformers/visitors/toOrchestrationVisitor.ts index 566941ba..442d401d 100644 --- a/src/transformers/visitors/toOrchestrationVisitor.ts +++ b/src/transformers/visitors/toOrchestrationVisitor.ts @@ -12,6 +12,7 @@ import { interactsWithSecretVisitor, parentnewASTPointer, initialiseOrchestratio // collects increments and decrements into a string (for new commitment calculation) and array // (for collecting zokrates inputs) +// This function appears to be unused - consider removing it? const collectIncrements = (stateVarIndicator: StateVariableIndicator | MappingKey) => { const incrementsArray: any[] = []; let incrementsString = ''; @@ -817,7 +818,6 @@ const visitor = { const keyIndicator = path.scope.getReferencedIndicator(stateVarIndicator[`keyPath`].node, true); if (keyIndicator instanceof LocalVariableIndicator && !keyIndicator.isParam) localMappingKey = true; } - newNodes.generateProofNode.privateStates[ name ] = buildPrivateStateNode('GenerateProof', { diff --git a/test/contracts/KnownUnknown.zol b/test/contracts/KnownUnknown.zol index 2998a513..092a966d 100644 --- a/test/contracts/KnownUnknown.zol +++ b/test/contracts/KnownUnknown.zol @@ -19,7 +19,19 @@ contract Assign { unknown b += value; unknown x.prop1 += a; a+= value; - //unknown b -= value; + } + + + function add1( uint256 value ) public { + unknown b = b + value +a; + unknown x.prop1 += value + a; + unknown x.prop2 += value; + unknown b += value; + unknown x.prop1 += a; + a+= value; + unknown b -= 1; + unknown x.prop1 -= 1; + unknown x.prop2 -= 1; } function remove( uint256 value ) public { diff --git a/test/contracts/KnownUnknown1.zol b/test/contracts/KnownUnknown1.zol new file mode 100644 index 00000000..2675a808 --- /dev/null +++ b/test/contracts/KnownUnknown1.zol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: CC0 +pragma solidity ^0.8.0; +contract Assign { + secret uint256 private a; + secret uint256 private b; + mapping(address => uint256) private c; + + struct MyStruct { + uint256 prop1; + uint256 prop2; + } + + secret MyStruct public x; + + function add( uint256 value ) public { + a+= value; + unknown b += value +a; + } + + function add1(secret uint256 value ) public { + unknown b += value +a; + unknown b += c[msg.sender]; + } + + + function remove( uint256 value ) public { + a -= 15; + unknown b = b - a + value; + b -= a - value; + b -= a + value; + b -= (a+ value); + } + +} \ No newline at end of file From 5d4cc4ee0c335c61dbb21cfe73e9aa530d741cc0 Mon Sep 17 00:00:00 2001 From: Lydia Garms Date: Mon, 29 Jul 2024 15:53:22 +0100 Subject: [PATCH 28/33] fix: when there is only accessed only variables and incremented variables ensure the nullifier root is sent to the contract and that input length is correct --- .../raw/ContractBoilerplateGenerator.ts | 2 +- .../javascript/raw/toOrchestration.ts | 9 ++++++--- test/contracts/KnownUnknown1.zol | 20 +++++++++++++------ 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/boilerplate/contract/solidity/raw/ContractBoilerplateGenerator.ts b/src/boilerplate/contract/solidity/raw/ContractBoilerplateGenerator.ts index 34ba8009..4d787ae4 100644 --- a/src/boilerplate/contract/solidity/raw/ContractBoilerplateGenerator.ts +++ b/src/boilerplate/contract/solidity/raw/ContractBoilerplateGenerator.ts @@ -210,7 +210,7 @@ class ContractBoilerplateGenerator { uint256[] memory inputs = new uint256[](${[ 'customInputs.length', ...(newNullifiers ? ['newNullifiers.length'] : []), - ...(commitmentRoot ? ['(newNullifiers.length > 0 ? 3 : 0)'] : []), // newNullifiers and commitmentRoot are always submitted together (regardless of use case). It's just that nullifiers aren't always stored (when merely accessing a state). and commitmentRoot are always submitted together (regardless of use case). It's just that nullifiers aren't always stored (when merely accessing a state). + ...(commitmentRoot ? ['(newNullifiers.length > 0 ? 3 : 0) + (((_inputs.nullifierRoot != 0) && (_inputs.latestNullifierRoot == 0)) ? 2 : 0)'] : []), // If there are new nullifiers then we need the nullier root, the latest nullifier root and the commitment root, but if the nullifier root is included but not the latest nullifier root (i.e. there is an accessed only state variable) then we only need 2 inputs. ...(newCommitments ? ['newCommitments.length'] : []), ...(encryptionRequired ? ['encInputsLen'] : []), ].join(' + ')});`, diff --git a/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts b/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts index 35f498e9..296a5c19 100644 --- a/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts +++ b/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts @@ -94,9 +94,12 @@ export const sendTransactionBoilerplate = (node: any) => { // whole if (!stateNode.reinitialisedOnly) output[2].push(`${privateStateName}_root.integer`); - if (!stateNode.accessedOnly && !stateNode.reinitialisedOnly) { - output[1].push(`${privateStateName}_nullifier.integer`); - output[0].push(`${privateStateName}_nullifierRoot.integer`,`${privateStateName}_newNullifierRoot.integer`); + if (!stateNode.reinitialisedOnly) { + output[0].push(`${privateStateName}_nullifierRoot.integer`) + if (!stateNode.accessedOnly) { + output[1].push(`${privateStateName}_nullifier.integer`); + output[0].push(`${privateStateName}_newNullifierRoot.integer`); + } } if (!stateNode.accessedOnly && !stateNode.burnedOnly) output[3].push(`${privateStateName}_newCommitment.integer`); diff --git a/test/contracts/KnownUnknown1.zol b/test/contracts/KnownUnknown1.zol index 2675a808..abad2d5e 100644 --- a/test/contracts/KnownUnknown1.zol +++ b/test/contracts/KnownUnknown1.zol @@ -3,7 +3,7 @@ pragma solidity ^0.8.0; contract Assign { secret uint256 private a; secret uint256 private b; - mapping(address => uint256) private c; + secret mapping(uint256 => uint256) private c; struct MyStruct { uint256 prop1; @@ -15,20 +15,28 @@ contract Assign { function add( uint256 value ) public { a+= value; unknown b += value +a; + c[0] += value; } function add1(secret uint256 value ) public { unknown b += value +a; - unknown b += c[msg.sender]; + unknown b += c[0]; + } + + function add2(secret uint256 value ) public { + unknown b = b + a -value; + unknown b += (a - value); } function remove( uint256 value ) public { a -= 15; - unknown b = b - a + value; - b -= a - value; - b -= a + value; - b -= (a+ value); + //unknown b = b - a + value; + //unknown b = b - a - value; + //b -= a - value; + //b -= a + value; + //b -= (a+ value); + b -= (a - value); } } \ No newline at end of file From 1136449c189a2d003a39452a5f2b190411c4358b Mon Sep 17 00:00:00 2001 From: Lydia Garms Date: Mon, 29 Jul 2024 16:22:47 +0100 Subject: [PATCH 29/33] fix: in orchestration when encrypting mapping key (backup) generalise first in case it is an integer --- .../orchestration/javascript/raw/boilerplate-generator.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts b/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts index eb40b259..e3de4947 100644 --- a/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts +++ b/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts @@ -605,7 +605,7 @@ encryptBackupPreimage = { ${valueName}]`; varName += ` a`; } else { - plainText = `[BigInt(${saltName}.hex(32)), BigInt(${mappingKey}.hex(32)), + plainText = `[BigInt(${saltName}.hex(32)), BigInt(generalise(${mappingKey}).hex(32)), BigInt(generalise(${stateName}_stateVarIdInit).hex(32)), ${valueName}]`; varName += ` a`; From d9b616ca0619d889f29a1571fe393b1927810b6a Mon Sep 17 00:00:00 2001 From: Lydia Garms Date: Tue, 30 Jul 2024 16:40:44 +0100 Subject: [PATCH 30/33] fix: allow for += that counts as a decrement because decremented elsewhere in the function --- src/codeGenerators/orchestration/nodejs/toOrchestration.ts | 7 +++++-- src/transformers/visitors/toOrchestrationVisitor.ts | 2 ++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/codeGenerators/orchestration/nodejs/toOrchestration.ts b/src/codeGenerators/orchestration/nodejs/toOrchestration.ts index 76af2e34..75a3ec92 100644 --- a/src/codeGenerators/orchestration/nodejs/toOrchestration.ts +++ b/src/codeGenerators/orchestration/nodejs/toOrchestration.ts @@ -133,7 +133,9 @@ export default function codeGenerator(node: any, options: any = {}): any { let increments; if (node.expression.operator === '+='){ increments = codeGenerator(node.expression.rightHandSide); - return `\n${privateStateName}_newCommitmentValue = generalise(parseInt(${privateStateName}_newCommitmentValue.integer, 10) + ${increments});\n`; + // Although we have += in the case that the indicator is decremented elsewhere in the function, we need to subtract the increments. + if (!node.indicatorDecremented) return `\n${privateStateName}_newCommitmentValue = generalise(parseInt(${privateStateName}_newCommitmentValue.integer, 10) + ${increments});\n`; + if (node.indicatorDecremented) return `\n${privateStateName}_newCommitmentValue = generalise(parseInt(${privateStateName}_newCommitmentValue.integer, 10) - (${increments}));\n`; } if (node.expression.operator === '-='){ increments = codeGenerator(node.expression.rightHandSide); @@ -146,7 +148,8 @@ export default function codeGenerator(node: any, options: any = {}): any { return `\n${privateStateName}_newCommitmentValue = generalise(parseInt(${privateStateName}_newCommitmentValue.integer, 10) - (${increments}));\n`; } increments = increments.replace(new RegExp(privateStateName, 'g'), `${privateStateName}_newCommitmentValue`); - return `\n${privateStateName}_newCommitmentValue = generalise(${increments});\n`; + if (!node.indicatorDecremented) return `\n${privateStateName}_newCommitmentValue = generalise(${increments});\n`; + if (node.indicatorDecremented) return `\n${privateStateName}_newCommitmentValue = generalise(\nparseInt(${privateStateName}_newCommitmentValue.integer, 10) -(${increments}));\n`; } } diff --git a/src/transformers/visitors/toOrchestrationVisitor.ts b/src/transformers/visitors/toOrchestrationVisitor.ts index 442d401d..2923146e 100644 --- a/src/transformers/visitors/toOrchestrationVisitor.ts +++ b/src/transformers/visitors/toOrchestrationVisitor.ts @@ -1551,6 +1551,8 @@ const visitor = { decrementsSecretState: node.expression.isDecremented, privateStateName: name, }); + newNode.indicatorIncremented= indicator.isIncremented; + newNode.indicatorDecremented= indicator.isDecremented; node._newASTPointer = newNode; parent._newASTPointer.push(newNode); From 301261b6ed8a4005d24e07aef21243cc17d0f457 Mon Sep 17 00:00:00 2001 From: Lydia Garms Date: Wed, 31 Jul 2024 14:10:28 +0100 Subject: [PATCH 31/33] fix: increments and decrements in same function - avoid negative numbers in orchestration --- .../javascript/raw/boilerplate-generator.ts | 9 +++++++-- .../orchestration/nodejs/toOrchestration.ts | 13 +++++++++---- test/contracts/KnownUnknown.zol | 6 +++--- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts b/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts index e3de4947..bb076de5 100644 --- a/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts +++ b/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts @@ -132,6 +132,8 @@ class BoilerplateGenerator { \nlet ${stateName}_preimage = await getCommitmentsById(${stateName}_stateVarId); \n ${structProperties.map(sp => `let ${stateName}_${sp}_newCommitmentValue = generalise(0);\n`).join('')} + \n + ${structProperties.map(sp => `let ${stateName}_${sp}_newCommitmentValue_inc = generalise(0);\n`).join('')} `]; return [` \n\n// read preimage for decremented state @@ -139,7 +141,9 @@ class BoilerplateGenerator { ${stateVarIds.join('\n')} \nlet ${stateName}_preimage = await getCommitmentsById(${stateName}_stateVarId); \n - let ${stateName}_newCommitmentValue = generalise(0);` ]; + let ${stateName}_newCommitmentValue = generalise(0); + \n + let ${stateName}_newCommitmentValue_inc = generalise(0);` ]; case 'whole': switch (reinitialisedOnly) { case true: @@ -190,7 +194,7 @@ class BoilerplateGenerator { if (structProperties) return [` \n\n// First check if required commitments exist or not - \nconst ${stateName}_newCommitmentValue = generalise([${Object.values(structProperties).map((sp) => `${stateName}_${sp}_newCommitmentValue`)}]).all; + \nconst ${stateName}_newCommitmentValue = generalise([${Object.values(structProperties).map((sp) => `generalise(parseInt(${stateName}_${sp}_newCommitmentValue.integer, 10) - parseInt(${stateName}_${sp}_newCommitmentValue_inc.integer, 10))`)}]).all; \nlet [${stateName}_commitmentFlag, ${stateName}_0_oldCommitment, ${stateName}_1_oldCommitment] = getInputCommitments( publicKey.hex(32), ${stateName}_newCommitmentValue.integer, @@ -215,6 +219,7 @@ class BoilerplateGenerator { const ${stateName}_1_path = generalise(${stateName}_witness_1.path).all;\n`]; return [` \n\n// First check if required commitments exist or not + \n${stateName}_newCommitmentValue = generalise(parseInt(${stateName}_newCommitmentValue.integer, 10) - parseInt(${stateName}_newCommitmentValue_inc.integer, 10)); \nlet [${stateName}_commitmentFlag, ${stateName}_0_oldCommitment, ${stateName}_1_oldCommitment] = getInputCommitments( publicKey.hex(32), ${stateName}_newCommitmentValue.integer, diff --git a/src/codeGenerators/orchestration/nodejs/toOrchestration.ts b/src/codeGenerators/orchestration/nodejs/toOrchestration.ts index 75a3ec92..9a432fde 100644 --- a/src/codeGenerators/orchestration/nodejs/toOrchestration.ts +++ b/src/codeGenerators/orchestration/nodejs/toOrchestration.ts @@ -135,7 +135,7 @@ export default function codeGenerator(node: any, options: any = {}): any { increments = codeGenerator(node.expression.rightHandSide); // Although we have += in the case that the indicator is decremented elsewhere in the function, we need to subtract the increments. if (!node.indicatorDecremented) return `\n${privateStateName}_newCommitmentValue = generalise(parseInt(${privateStateName}_newCommitmentValue.integer, 10) + ${increments});\n`; - if (node.indicatorDecremented) return `\n${privateStateName}_newCommitmentValue = generalise(parseInt(${privateStateName}_newCommitmentValue.integer, 10) - (${increments}));\n`; + if (node.indicatorDecremented) return `\n${privateStateName}_newCommitmentValue_inc = generalise(parseInt(${privateStateName}_newCommitmentValue_inc.integer, 10) + ${increments});\n`; } if (node.expression.operator === '-='){ increments = codeGenerator(node.expression.rightHandSide); @@ -147,9 +147,14 @@ export default function codeGenerator(node: any, options: any = {}): any { increments = increments.replace(new RegExp(`${privateStateName}.integer`, 'g'), `0`); return `\n${privateStateName}_newCommitmentValue = generalise(parseInt(${privateStateName}_newCommitmentValue.integer, 10) - (${increments}));\n`; } - increments = increments.replace(new RegExp(privateStateName, 'g'), `${privateStateName}_newCommitmentValue`); - if (!node.indicatorDecremented) return `\n${privateStateName}_newCommitmentValue = generalise(${increments});\n`; - if (node.indicatorDecremented) return `\n${privateStateName}_newCommitmentValue = generalise(\nparseInt(${privateStateName}_newCommitmentValue.integer, 10) -(${increments}));\n`; + if (!node.indicatorDecremented) { + increments = increments.replace(new RegExp(privateStateName, 'g'), `${privateStateName}_newCommitmentValue`); + return `\n${privateStateName}_newCommitmentValue = generalise(${increments});\n`; + } + if (node.indicatorDecremented) { + increments = increments.replace(new RegExp(privateStateName, 'g'), `${privateStateName}_newCommitmentValue_inc`); + return `\n${privateStateName}_newCommitmentValue_inc = generalise(\n${increments});\n`; + } } } diff --git a/test/contracts/KnownUnknown.zol b/test/contracts/KnownUnknown.zol index 092a966d..939673f6 100644 --- a/test/contracts/KnownUnknown.zol +++ b/test/contracts/KnownUnknown.zol @@ -29,9 +29,9 @@ contract Assign { unknown b += value; unknown x.prop1 += a; a+= value; - unknown b -= 1; - unknown x.prop1 -= 1; - unknown x.prop2 -= 1; + unknown b -= 5*value + a; + unknown x.prop1 -= 5*value + a; + unknown x.prop2 -= 2*value; } function remove( uint256 value ) public { From 4bcae06ac8068ef98aba6308643dd5a6da2fd5ab Mon Sep 17 00:00:00 2001 From: Lydia Garms Date: Wed, 31 Jul 2024 17:33:13 +0100 Subject: [PATCH 32/33] fix: in orchestration nullifierRoot is sent as a newNullifierRoot in SendTransaction --- .../javascript/raw/toOrchestration.ts | 61 ++++++++++--------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts b/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts index 296a5c19..a8d141a8 100644 --- a/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts +++ b/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts @@ -56,13 +56,14 @@ const stateVariableIds = (node: any) => { const Orchestrationbp = new OrchestrationBP(); export const sendTransactionBoilerplate = (node: any) => { const { privateStates } = node; - const output: string[][] = [[],[],[],[],[],[]]; + const output: string[][] = [[],[],[],[],[],[],[]]; // output[0] = nullifier root(s) - // output[1] = arr of nullifiers - // output[2] = commitments root(s) - // output[3] = arr of commitments - // output[4] = arr of cipherText - // output[5] = arr of enc keys + // output[1] = nullifier root(s) + // output[2] = arr of nullifiers + // output[3] = commitments root(s) + // output[4] = arr of commitments + // output[5] = arr of cipherText + // output[6] = arr of enc keys let privateStateName: string; let stateNode: any; for ([privateStateName, stateNode] of Object.entries(privateStates)) { @@ -71,20 +72,21 @@ export const sendTransactionBoilerplate = (node: any) => { switch (stateNode.nullifierRequired) { case true: // decrement - output[2].push(`${privateStateName}_root.integer`); - output[0].push(`${privateStateName}_nullifierRoot.integer`, `${privateStateName}_newNullifierRoot.integer`); - output[1].push( + output[3].push(`${privateStateName}_root.integer`); + output[0].push(`${privateStateName}_nullifierRoot.integer`); + output[1].push(`${privateStateName}_newNullifierRoot.integer`); + output[2].push( `${privateStateName}_0_nullifier.integer, ${privateStateName}_1_nullifier.integer`, ); - output[3].push(`${privateStateName}_2_newCommitment.integer`); + output[4].push(`${privateStateName}_2_newCommitment.integer`); break; case false: default: // increment - output[3].push(`${privateStateName}_newCommitment.integer`); + output[4].push(`${privateStateName}_newCommitment.integer`); if (stateNode.encryptionRequired) { - output[4].push(`${privateStateName}_cipherText`); - output[5].push(`${privateStateName}_encKey`); + output[5].push(`${privateStateName}_cipherText`); + output[6].push(`${privateStateName}_encKey`); } break; } @@ -93,19 +95,19 @@ export const sendTransactionBoilerplate = (node: any) => { default: // whole if (!stateNode.reinitialisedOnly) - output[2].push(`${privateStateName}_root.integer`); + output[3].push(`${privateStateName}_root.integer`); if (!stateNode.reinitialisedOnly) { output[0].push(`${privateStateName}_nullifierRoot.integer`) if (!stateNode.accessedOnly) { - output[1].push(`${privateStateName}_nullifier.integer`); - output[0].push(`${privateStateName}_newNullifierRoot.integer`); + output[2].push(`${privateStateName}_nullifier.integer`); + output[1].push(`${privateStateName}_newNullifierRoot.integer`); } } if (!stateNode.accessedOnly && !stateNode.burnedOnly) - output[3].push(`${privateStateName}_newCommitment.integer`); + output[4].push(`${privateStateName}_newCommitment.integer`); if (stateNode.encryptionRequired) { - output[4].push(`${privateStateName}_cipherText`); - output[5].push(`${privateStateName}_encKey`); + output[5].push(`${privateStateName}_cipherText`); + output[6].push(`${privateStateName}_encKey`); } break; @@ -924,19 +926,18 @@ export const OrchestrationCodeBoilerPlate: any = (node: any) => { } params[0] = sendTransactionBoilerplate(node); - if(!node.returnInputs[0] && !params[0][4][0]) returnInputs.push(`1`); // If there are no return, circuit's default return is true + if(!node.returnInputs[0] && !params[0][5][0]) returnInputs.push(`1`); // If there are no return, circuit's default return is true // params[0] = arr of nullifier root(s) // params[1] = arr of commitment root(s) // params[2] = arr of nullifiers // params[3] = arr of commitments - (params[0][0][0]) ? params[0][0][0] = ` ${params[0][0][0]}, ` : params[0][0][0] = ` 0 , ` ; // nullifierRoot - array // Default value for the struct - (params[0][0][1]) ? params[0][0][1] = ` ${params[0][0][1]}, ` : params[0][0][1] = ` 0, `; - (params[0][2][0]) ? params[0][2] = ` ${params[0][2][0]},` : params[0][2] = ` 0 , ` ; // commitmentRoot - array - (params[0][1][0]) ? params[0][1] = ` [${params[0][1]}],` : params[0][1] = ` [], `; // nullifiers - array - (params[0][3][0]) ? params[0][3] = `[${params[0][3]}],` : params[0][3] = ` [], `; // commitments - array - (params[0][4][0]) ? params[0][4] = `[${params[0][4]}],` : params[0][4] = ` [], `; // cipherText - array of arrays - (params[0][5][0]) ? params[0][5] = `[${params[0][5]}],`: params[0][5] = ` [], `;// cipherText - array of arrays - + (params[0][0][0]) ? params[0][0] = ` ${params[0][0][0]}, ` : params[0][0] = ` 0 , ` ; // nullifierRoot - array // Default value for the struct + (params[0][1][0]) ? params[0][1] = ` ${params[0][1][0]}, ` : params[0][1] = ` 0, `; + (params[0][3][0]) ? params[0][3] = ` ${params[0][3][0]},` : params[0][3] = ` 0 , ` ; // commitmentRoot - array + (params[0][2][0]) ? params[0][2] = ` [${params[0][2]}],` : params[0][2] = ` [], `; // nullifiers - array + (params[0][4][0]) ? params[0][4] = `[${params[0][4]}],` : params[0][4] = ` [], `; // commitments - array + (params[0][5][0]) ? params[0][5] = `[${params[0][5]}],` : params[0][5] = ` [], `; // cipherText - array of arrays + (params[0][6][0]) ? params[0][6] = `[${params[0][6]}],`: params[0][6] = ` [], `;// cipherText - array of arrays if (node.functionName === 'cnstrctr') return { statements: [ @@ -944,7 +945,7 @@ export const OrchestrationCodeBoilerPlate: any = (node: any) => { \nBackupData.forEach((element) => { element.cipherText = element.cipherText.map(ct => generalise(ct).hex(32)); }); - \nconst tx = { proofInput: [{customInputs: [${returnInputs}], nullifierRoot: ${params[0][0][0]} latestNullifierRoot:${params[0][0][1]} newNullifiers: ${params[0][1]} commitmentRoot:${params[0][2]} newCommitments: ${params[0][3]}}, proof, BackupData], nullifiers: ${params[0][1]} isNullfiersAdded: false, ${node.publicInputs?.map(input => `${input}: ${input}.integer,`)}};` + \nconst tx = { proofInput: [{customInputs: [${returnInputs}], nullifierRoot: ${params[0][0]} latestNullifierRoot:${params[0][1]} newNullifiers: ${params[0][2]} commitmentRoot:${params[0][3]} newCommitments: ${params[0][4]}}, proof, BackupData], nullifiers: ${params[0][2]} isNullfiersAdded: false, ${node.publicInputs?.map(input => `${input}: ${input}.integer,`)}};` ] } @@ -954,7 +955,7 @@ export const OrchestrationCodeBoilerPlate: any = (node: any) => { statements: [ `\n\n// Send transaction to the blockchain: \nconst txData = await instance.methods - .${node.functionName}(${lines.length > 0 ? `${lines},`: ``} {customInputs: [${returnInputs}], nullifierRoot: ${params[0][0][0]} latestNullifierRoot:${params[0][0][1]} newNullifiers: ${params[0][1]} commitmentRoot:${params[0][2]} newCommitments: ${params[0][3]} cipherText:${params[0][4]} encKeys: ${params[0][5]}}, proof, BackupData).encodeABI(); + .${node.functionName}(${lines.length > 0 ? `${lines},`: ``} {customInputs: [${returnInputs}], nullifierRoot: ${params[0][0]} latestNullifierRoot:${params[0][1]} newNullifiers: ${params[0][2]} commitmentRoot:${params[0][3]} newCommitments: ${params[0][4]} cipherText:${params[0][5]} encKeys: ${params[0][6]}}, proof, BackupData).encodeABI(); \n let txParams = { from: config.web3.options.defaultAccount, to: contractAddr, From eca8c2e197854e0c54b89d014020f6f9758db325 Mon Sep 17 00:00:00 2001 From: Lydia Garms Date: Thu, 1 Aug 2024 12:40:17 +0100 Subject: [PATCH 33/33] fix: for mapping of struct in orchestration full name not appearing --- src/transformers/visitors/toOrchestrationVisitor.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/transformers/visitors/toOrchestrationVisitor.ts b/src/transformers/visitors/toOrchestrationVisitor.ts index 2923146e..e5998269 100644 --- a/src/transformers/visitors/toOrchestrationVisitor.ts +++ b/src/transformers/visitors/toOrchestrationVisitor.ts @@ -1454,7 +1454,7 @@ const visitor = { if (!lhs) lhs = node.expression.subExpression; indicator = scope.getReferencedIndicator(lhs, true); - const name = indicator.isMapping + let name = indicator.isMapping ? indicator.name .replace('[', '_') .replace(']', '') @@ -1540,6 +1540,9 @@ const visitor = { return; } } + if (indicator.isMapping && indicator.isStruct){ + name = `${name}_${node.expression.leftHandSide.memberName}`; + } // if its an incrementation, we need to know it happens but not copy it over if (node.expression.isIncremented && indicator.isPartitioned) { const newNode = buildNode(node.nodeType, {