From 2430289a27949b03275116e57f589ed730d5529d Mon Sep 17 00:00:00 2001 From: Swati Rawal Date: Fri, 23 Aug 2024 08:47:08 +0100 Subject: [PATCH 01/17] chore: fixed the circuits --- .../circuit/zokrates/toCircuit.ts | 2 ++ ...rchestrationInternalFunctionCallVisitor.ts | 30 ++++++++++++------- src/transformers/visitors/toCircuitVisitor.ts | 15 +++++++--- test/contracts/Assign-Return1.zol | 9 ++++-- test/contracts/for-InternalFunctionCall.zol | 4 +-- test/contracts/for-loop.zol | 1 + 6 files changed, 42 insertions(+), 19 deletions(-) diff --git a/src/codeGenerators/circuit/zokrates/toCircuit.ts b/src/codeGenerators/circuit/zokrates/toCircuit.ts index 62667eaad..fe12e1989 100644 --- a/src/codeGenerators/circuit/zokrates/toCircuit.ts +++ b/src/codeGenerators/circuit/zokrates/toCircuit.ts @@ -160,7 +160,9 @@ function codeGenerator(node: any) { case 'VariableDeclarationStatement': { const declarations = node.declarations.map(codeGenerator).join(', '); if (!node.initialValue) return `${declarations} = ${node.declarations.map(n => n.typeName.name === 'bool' ? 'false' : 0)}`; + if(node.initialValue.nodeType === 'InternalFunctionCall') return `${declarations} = ${node.initialValue.name}`; const initialValue = codeGenerator(node.initialValue); + return `${declarations} = ${initialValue}`; } diff --git a/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts b/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts index 273174ad4..b207b073a 100644 --- a/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts +++ b/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts @@ -306,14 +306,24 @@ const internalCallVisitor = { childNode.body.statements[id-1] = statenode; node.body.statements.forEach(kidNode =>{ if(kidNode.nodeType === 'ExpressionStatement'&& kidNode.expression.name === state.internalFncName[index]) { - kidNode.expression = Object.assign(kidNode.expression,statenode.initialValue); + if (kidNode.expression.operator) { + const newExpressionNode = Object.assign(cloneDeep(kidNode.expression), statenode.initialValue); + node.body.statements.push(newExpressionNode); + } else { + Object.assign(kidNode.expression, statenode.initialValue); + } } + }); - childNode.body.statements[id-1].initialValue =undefined; + childNode.body.statements[id-1].initialValue = undefined; } else{ - node.body.statements.forEach(kidNode =>{ - if(kidNode.nodeType === 'ExpressionStatement'&& kidNode.expression.name === state.internalFncName[index]) { - kidNode.expression = Object.assign(kidNode.expression,statenode.expression); + node.body.statements.forEach(kidNode => { + if(kidNode.nodeType === 'ExpressionStatement' && kidNode.expression.name === state.internalFncName[index]) { + if(kidNode.expression.operator) { + const newExpressionNode = Object.assign(cloneDeep(kidNode.expression), statenode.expression); + node.body.statements.push(newExpressionNode); + } + kidNode.expression = Object.assign(kidNode.expression, statenode.expression); } }); } @@ -321,7 +331,7 @@ const internalCallVisitor = { }); }); // remove multiple variable declarations - childNode.body.statements.forEach((node1, index1)=> { + childNode.body.statements.forEach((node1, index1) => { let isDecDeleted = false; if(node1.nodeType === 'VariableDeclarationStatement'){ childNode.body.statements.forEach((node2, index2)=> { @@ -342,7 +352,7 @@ const internalCallVisitor = { if(statenode.nodeType === 'VariableDeclarationStatement'){ childNode.body.statements[id-1] = statenode; node.body.statements.forEach(kidNode =>{ - if(kidNode.nodeType === 'ExpressionStatement'&& kidNode.expression.name === state.internalFncName[index]) { + if(kidNode.nodeType === 'ExpressionStatement' && kidNode.expression.name === state.internalFncName[index]) { kidNode.expression = Object.assign(kidNode.expression,statenode.initialValue); node.body.statements?.splice(node.body.statements.indexOf(kidNode)+1, 0, state.newStatementList[stateid+1]); } @@ -382,7 +392,7 @@ const internalCallVisitor = { } }); }); - node.privateStates = Object.assign(node.privateStates,statenode.privateStates); + node.privateStates = Object.assign(node.privateStates, statenode.privateStates); } }); break; @@ -397,7 +407,7 @@ const internalCallVisitor = { } }); }); - node.privateStates = Object.assign(node.privateStates,statenode.privateStates); + node.privateStates = Object.assign(node.privateStates, statenode.privateStates); } }); break; @@ -405,7 +415,7 @@ const internalCallVisitor = { case 'CalculateCommitment': { state.newPostStatementList.forEach(statenode => { if(statenode.nodeType === 'CalculateCommitment'){ - node.privateStates = Object.assign(node.privateStates,statenode.privateStates); + node.privateStates = Object.assign(node.privateStates, statenode.privateStates); } }); break; diff --git a/src/transformers/visitors/toCircuitVisitor.ts b/src/transformers/visitors/toCircuitVisitor.ts index db99291ac..c81c03c17 100644 --- a/src/transformers/visitors/toCircuitVisitor.ts +++ b/src/transformers/visitors/toCircuitVisitor.ts @@ -722,6 +722,7 @@ const visitor = { state.skipSubNodes = true; return; } + const newNode = buildNode('VariableDeclarationStatement'); node._newASTPointer = newNode; @@ -1579,14 +1580,20 @@ const visitor = { state.circuitImport.push({isImported: 'true', modVars: modifiedVariables, callingFunction: callingfnDefPath.node.name}); else state.circuitImport.push({isImported: 'false', modVars: modifiedVariables, callingFunction: callingfnDefPath.node.name}); - - - const newNode = buildNode('InternalFunctionCall', { +let newNode: any; +if(parent.nodeType === 'VariableDeclarationStatement') { + // console.log(functionReferncedNode.node.returnParameters); + newNode = buildNode('InternalFunctionCall', { + name: functionReferncedNode.node.returnParameters.parameters[0].name, + internalFunctionInteractsWithSecret: internalFunctionInteractsWithSecret, + }); +} else + { newNode = buildNode('InternalFunctionCall', { name: node.expression.name, internalFunctionInteractsWithSecret: internalFunctionInteractsWithSecret, CircuitArguments: [], CircuitReturn:[], - }); + });} const fnNode = buildNode('InternalFunctionBoilerplate', { name: node.expression.name, internalFunctionInteractsWithSecret: internalFunctionInteractsWithSecret, diff --git a/test/contracts/Assign-Return1.zol b/test/contracts/Assign-Return1.zol index 5c8367165..c08560391 100644 --- a/test/contracts/Assign-Return1.zol +++ b/test/contracts/Assign-Return1.zol @@ -5,14 +5,17 @@ pragma solidity ^0.8.0; contract Assign { secret uint256 private a; + secret uint256 private b; - function add( uint256 value) public returns (uint256) { + function add( secret uint256 value) public returns (uint256) { a += value; - return a; + b += value; + return b; } function remove(secret uint256 value) public { - a -= value; + secret uint256 value1 = add(value); + a -= value + value1; } } diff --git a/test/contracts/for-InternalFunctionCall.zol b/test/contracts/for-InternalFunctionCall.zol index 43d4c5efa..b780e5431 100644 --- a/test/contracts/for-InternalFunctionCall.zol +++ b/test/contracts/for-InternalFunctionCall.zol @@ -5,7 +5,7 @@ pragma solidity ^0.8.0; contract Assign { secret uint256 private a; - + secret uint256 private b; function remove(secret uint256 value) public { a -= value; uint k; @@ -15,6 +15,6 @@ contract Assign { } function add(secret uint256 value) public { known a += value; - a += 1; + b += 1; } } diff --git a/test/contracts/for-loop.zol b/test/contracts/for-loop.zol index 16d6c288e..d2754a868 100644 --- a/test/contracts/for-loop.zol +++ b/test/contracts/for-loop.zol @@ -10,6 +10,7 @@ function add(uint256 j) public { uint256 i; for(i =0 ; i<5 ; i++) { z += j; + z += 1; } } } From 2a444f99ee5526a61f9c2f43b73ced639cec83d4 Mon Sep 17 00:00:00 2001 From: Swati Rawal Date: Tue, 27 Aug 2024 13:26:27 +0100 Subject: [PATCH 02/17] chore: orchestration fixes --- .../orchestration/nodejs/toOrchestration.ts | 2 ++ .../orchestrationInternalFunctionCallVisitor.ts | 13 +++++++++++-- src/types/solidity-types.ts | 1 + test/contracts/Assign-Return1.zol | 1 - 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/codeGenerators/orchestration/nodejs/toOrchestration.ts b/src/codeGenerators/orchestration/nodejs/toOrchestration.ts index 9a432fdec..ccf35638a 100644 --- a/src/codeGenerators/orchestration/nodejs/toOrchestration.ts +++ b/src/codeGenerators/orchestration/nodejs/toOrchestration.ts @@ -109,8 +109,10 @@ export default function codeGenerator(node: any, options: any = {}): any { if (!node.initialValue.nodeType) return `\nlet ${codeGenerator(node.declarations[0])};` // local var dec if (node.initialValue.nodeType === 'Literal' && node.isInitializationExpression) return `\nlet ${codeGenerator(node.declarations[0])} = ${codeGenerator(node.initialValue)};`; + if(node.initialValue.nodeType === 'InternalFunctionCall') return `\nlet ${codeGenerator(node.declarations[0])} = generalise(${node.initialValue.name}.integer);`; return `\nlet ${codeGenerator(node.declarations[0])} = generalise(${codeGenerator(node.initialValue)});`; } + return `\nlet ${codeGenerator(node.initialValue)};`; } diff --git a/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts b/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts index b207b073a..9f321f1c3 100644 --- a/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts +++ b/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts @@ -267,7 +267,8 @@ const internalCallVisitor = { let newVarDecs = []; childNode.body.statements.forEach((node1, index1)=> { state.varNames = []; - if (!(node1.expression && node1.expression?.nodeType === 'InternalFunctionCall')){ + // check the node except the InternalFunctionCall node + if (!((node1.expression &&node1.expression?.nodeType === 'InternalFunctionCall') || (node1.initialValue && node1.initialValue?.nodeType === 'InternalFunctionCall'))){ traverseNodesFast(node1, findVarVisitor, state); } state.varNames.forEach((varName) => { @@ -517,10 +518,18 @@ FunctionCall: { state.circuitImport.push('true'); else state.circuitImport.push('false'); - const newNode = buildNode('InternalFunctionCall', { + let newNode; + if(parent.nodeType === 'VariableDeclarationStatement') { + newNode = buildNode('InternalFunctionCall', { + name: functionReferncedNode.node.returnParameters.parameters[0].name, + internalFunctionInteractsWithSecret: internalFunctionInteractsWithSecret, + }); + } else { + newNode = buildNode('InternalFunctionCall', { name: node.expression.name, internalFunctionInteractsWithSecret: internalFunctionInteractsWithSecret, }); + } node._newASTPointer = newNode ; if (Array.isArray(parent._newASTPointer[path.containerName])) { parent._newASTPointer[path.containerName].push(newNode); diff --git a/src/types/solidity-types.ts b/src/types/solidity-types.ts index e7899da6c..ef1e7c0ca 100644 --- a/src/types/solidity-types.ts +++ b/src/types/solidity-types.ts @@ -77,6 +77,7 @@ export function getVisitableKeys(nodeType: string): string[] { // And again, if we haven't recognized the nodeType then we'll throw an // error. default: + console.log(nodeType); throw new TypeError(nodeType); } } diff --git a/test/contracts/Assign-Return1.zol b/test/contracts/Assign-Return1.zol index c08560391..da1ea7d14 100644 --- a/test/contracts/Assign-Return1.zol +++ b/test/contracts/Assign-Return1.zol @@ -16,6 +16,5 @@ contract Assign { function remove(secret uint256 value) public { secret uint256 value1 = add(value); a -= value + value1; - } } From 4864c5898b168a482d1320d1fc4eb7c329689aca Mon Sep 17 00:00:00 2001 From: Swati Rawal Date: Tue, 27 Aug 2024 13:28:20 +0100 Subject: [PATCH 03/17] chore: orchestration fixes --- src/types/solidity-types.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/types/solidity-types.ts b/src/types/solidity-types.ts index ef1e7c0ca..e7899da6c 100644 --- a/src/types/solidity-types.ts +++ b/src/types/solidity-types.ts @@ -77,7 +77,6 @@ export function getVisitableKeys(nodeType: string): string[] { // And again, if we haven't recognized the nodeType then we'll throw an // error. default: - console.log(nodeType); throw new TypeError(nodeType); } } From e28f6d1a837c935f1d016ee1b5b05b7102fb2bf1 Mon Sep 17 00:00:00 2001 From: Swati Rawal Date: Tue, 27 Aug 2024 15:27:53 +0100 Subject: [PATCH 04/17] chore: contract fixes --- .../raw/FunctionBoilerplateGenerator.ts | 3 ++- .../circuit/zokrates/toCircuit.ts | 2 +- .../contract/solidity/toContract.ts | 2 ++ src/transformers/visitors/toCircuitVisitor.ts | 11 +++++----- .../visitors/toContractVisitor.ts | 4 +--- test/contracts/Assign-Return1.zol | 1 + .../contracts/internalFunctionCall-return.zol | 21 +++++++++++++++++++ 7 files changed, 34 insertions(+), 10 deletions(-) create mode 100644 test/contracts/internalFunctionCall-return.zol diff --git a/src/boilerplate/contract/solidity/raw/FunctionBoilerplateGenerator.ts b/src/boilerplate/contract/solidity/raw/FunctionBoilerplateGenerator.ts index 39c54d20a..83be0dc60 100644 --- a/src/boilerplate/contract/solidity/raw/FunctionBoilerplateGenerator.ts +++ b/src/boilerplate/contract/solidity/raw/FunctionBoilerplateGenerator.ts @@ -143,7 +143,8 @@ class FunctionBoilerplateGenerator { : []), ...(newCommitments ? [` // this seems silly (it is) but its the only way to get the event to emit properly - emit EncryptedBackupData(BackupData);`] + emit EncryptedBackupData(BackupData); + `] : []), ]; }, diff --git a/src/codeGenerators/circuit/zokrates/toCircuit.ts b/src/codeGenerators/circuit/zokrates/toCircuit.ts index fe12e1989..a7c2b96bf 100644 --- a/src/codeGenerators/circuit/zokrates/toCircuit.ts +++ b/src/codeGenerators/circuit/zokrates/toCircuit.ts @@ -160,7 +160,7 @@ function codeGenerator(node: any) { case 'VariableDeclarationStatement': { const declarations = node.declarations.map(codeGenerator).join(', '); if (!node.initialValue) return `${declarations} = ${node.declarations.map(n => n.typeName.name === 'bool' ? 'false' : 0)}`; - if(node.initialValue.nodeType === 'InternalFunctionCall') return `${declarations} = ${node.initialValue.name}`; + if(node.initialValue.nodeType === 'InternalFunctionCall') return node.internalFunctionInteractsWithSecret ? `${declarations} = ${node.initialValue.name}` : ``; const initialValue = codeGenerator(node.initialValue); return `${declarations} = ${initialValue}`; diff --git a/src/codeGenerators/contract/solidity/toContract.ts b/src/codeGenerators/contract/solidity/toContract.ts index 3d59e6703..528d02fcd 100644 --- a/src/codeGenerators/contract/solidity/toContract.ts +++ b/src/codeGenerators/contract/solidity/toContract.ts @@ -146,6 +146,8 @@ function codeGenerator(node: any) { if(node.initialValue) initialValue = codeGenerator(node.initialValue); if (!initialValue || initialValue === '') return `${declarations};`; + if(node.initialValue.nodeType === 'InternalFunctionCall') return ` + ${declarations} = ${initialValue.replace(/\s+/g,' ').trim()}`; return ` ${declarations} = ${initialValue};`; } diff --git a/src/transformers/visitors/toCircuitVisitor.ts b/src/transformers/visitors/toCircuitVisitor.ts index c81c03c17..f5bb50269 100644 --- a/src/transformers/visitors/toCircuitVisitor.ts +++ b/src/transformers/visitors/toCircuitVisitor.ts @@ -1582,18 +1582,19 @@ const visitor = { state.circuitImport.push({isImported: 'false', modVars: modifiedVariables, callingFunction: callingfnDefPath.node.name}); let newNode: any; if(parent.nodeType === 'VariableDeclarationStatement') { - // console.log(functionReferncedNode.node.returnParameters); newNode = buildNode('InternalFunctionCall', { name: functionReferncedNode.node.returnParameters.parameters[0].name, - internalFunctionInteractsWithSecret: internalFunctionInteractsWithSecret, + internalFunctionInteractsWithSecret: internalFunctionInteractsWithSecret, // return }); -} else - { newNode = buildNode('InternalFunctionCall', { +} else + { + newNode = buildNode('InternalFunctionCall', { name: node.expression.name, internalFunctionInteractsWithSecret: internalFunctionInteractsWithSecret, CircuitArguments: [], CircuitReturn:[], - });} + }); + } const fnNode = buildNode('InternalFunctionBoilerplate', { name: node.expression.name, internalFunctionInteractsWithSecret: internalFunctionInteractsWithSecret, diff --git a/src/transformers/visitors/toContractVisitor.ts b/src/transformers/visitors/toContractVisitor.ts index 06f10742d..48b2adbb9 100644 --- a/src/transformers/visitors/toContractVisitor.ts +++ b/src/transformers/visitors/toContractVisitor.ts @@ -520,7 +520,7 @@ export default { // TODO interacts with secret AND public const subState = { interactsWithSecret: false }; path.traversePathsFast(interactsWithSecretVisitor, subState); - if (subState.interactsWithSecret) { + if (subState.interactsWithSecret && node.initialValue.nodeType != 'FunctionCall') { state.skipSubNodes = true; return; } @@ -841,7 +841,6 @@ DoWhileStatement: { enter(path: NodePath, state: any) { const { node, parent, scope } = path; let newNode: any; - // If this node is a require statement, it might include arguments which themselves are expressions which need to be traversed. So rather than build a corresponding 'assert' node upon entry, we'll first traverse into the arguments, build their nodes, and then upon _exit_ build the assert node. if (path.isRequireStatement() || path.isRevertStatement() || (node.expression.memberName && node.expression.memberName === 'push')) { // If the 'require' statement contains secret state variables, we'll presume the circuit will perform that logic, so we'll do nothing in the contract. @@ -882,7 +881,6 @@ DoWhileStatement: { if (path.isInternalFunctionCall()) { // External function calls are the fiddliest of things, because they must be retained in the Solidity contract, rather than brought into the circuit. With this in mind, it's easiest (from the pov of writing this transpiler) if External function calls appear at the very start or very end of a function. If they appear interspersed around the middle, we'd either need multiple circuits per Zolidity function, or we'd need a set of circuit parameters (non-secret params / return-params) per external function call, and both options are too painful for now. // TODO: need a warning message to this effect ^^^ - const functionReferncedNode = scope.getReferencedNode(node.expression); const params = functionReferncedNode.parameters.parameters; state.pubparams = []; diff --git a/test/contracts/Assign-Return1.zol b/test/contracts/Assign-Return1.zol index da1ea7d14..c08560391 100644 --- a/test/contracts/Assign-Return1.zol +++ b/test/contracts/Assign-Return1.zol @@ -16,5 +16,6 @@ contract Assign { function remove(secret uint256 value) public { secret uint256 value1 = add(value); a -= value + value1; + } } diff --git a/test/contracts/internalFunctionCall-return.zol b/test/contracts/internalFunctionCall-return.zol new file mode 100644 index 000000000..6f806001a --- /dev/null +++ b/test/contracts/internalFunctionCall-return.zol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: CC0 + +pragma solidity ^0.8.0; + +contract Assign { + + secret uint256 private a; + uint256 public b; + + function add( secret uint256 value, uint256 value1) public returns (uint256) { + a += value; + b += value1; + return b; + } + + function remove(secret uint256 value, uint256 value1) public { + uint256 c = add(value, value1); + b += c + 1; + a -= value + value1; + } +} \ No newline at end of file From beb16caaa8b32f799627020a97b35fda7434c389 Mon Sep 17 00:00:00 2001 From: Swati Rawal Date: Wed, 28 Aug 2024 16:02:45 +0100 Subject: [PATCH 05/17] chore: added a secret return fix --- .../circuit/zokrates/toCircuit.ts | 2 +- .../contract/solidity/toContract.ts | 8 ++++++-- ...rchestrationInternalFunctionCallVisitor.ts | 19 +++++++++++++++++- src/transformers/visitors/toCircuitVisitor.ts | 10 +++++++++- .../internalFunctionCall-return2.zol | 20 +++++++++++++++++++ 5 files changed, 54 insertions(+), 5 deletions(-) create mode 100644 test/contracts/internalFunctionCall-return2.zol diff --git a/src/codeGenerators/circuit/zokrates/toCircuit.ts b/src/codeGenerators/circuit/zokrates/toCircuit.ts index a7c2b96bf..39f9ab33e 100644 --- a/src/codeGenerators/circuit/zokrates/toCircuit.ts +++ b/src/codeGenerators/circuit/zokrates/toCircuit.ts @@ -160,7 +160,7 @@ function codeGenerator(node: any) { case 'VariableDeclarationStatement': { const declarations = node.declarations.map(codeGenerator).join(', '); if (!node.initialValue) return `${declarations} = ${node.declarations.map(n => n.typeName.name === 'bool' ? 'false' : 0)}`; - if(node.initialValue.nodeType === 'InternalFunctionCall') return node.internalFunctionInteractsWithSecret ? `${declarations} = ${node.initialValue.name}` : ``; + if(node.initialValue.nodeType === 'InternalFunctionCall') return `${declarations} = ${node.initialValue.name}`; const initialValue = codeGenerator(node.initialValue); return `${declarations} = ${initialValue}`; diff --git a/src/codeGenerators/contract/solidity/toContract.ts b/src/codeGenerators/contract/solidity/toContract.ts index 528d02fcd..42cce8663 100644 --- a/src/codeGenerators/contract/solidity/toContract.ts +++ b/src/codeGenerators/contract/solidity/toContract.ts @@ -140,14 +140,18 @@ function codeGenerator(node: any) { } case 'VariableDeclarationStatement': { + console.log(node); const declarations: string = node.declarations.map(codeGenerator).join(', '); if (declarations === '') return declarations; // when all are secret, we ignore them let initialValue; if(node.initialValue) initialValue = codeGenerator(node.initialValue); if (!initialValue || initialValue === '') return `${declarations};`; - if(node.initialValue.nodeType === 'InternalFunctionCall') return ` - ${declarations} = ${initialValue.replace(/\s+/g,' ').trim()}`; + if(node.initialValue.nodeType === 'InternalFunctionCall'){ + if(node.interactsWithSecret) return ; + return ` + ${declarations} = ${initialValue.replace(/\s+/g,' ').trim()}`; + } return ` ${declarations} = ${initialValue};`; } diff --git a/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts b/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts index 9f321f1c3..006af6366 100644 --- a/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts +++ b/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts @@ -520,10 +520,27 @@ FunctionCall: { state.circuitImport.push('false'); let newNode; if(parent.nodeType === 'VariableDeclarationStatement') { + const decNode = buildNode('VariableDeclarationStatement') + decNode.declarations.push(functionReferncedNode.node.returnParameters.parameters[0]._newASTPointer); + decNode.interactsWithSecret = true; + decNode.declarations[0].declarationType = 'state'; + decNode.declarations[0].isAccessed = true; + decNode.declarations[0].interactsWithSecret = true; + callingfnDefPath.node._newASTPointer.body.preStatements.splice(1,0,decNode); + const returnPara = functionReferncedNode.node.returnParameters.parameters[0].name; newNode = buildNode('InternalFunctionCall', { - name: functionReferncedNode.node.returnParameters.parameters[0].name, + name: returnPara, internalFunctionInteractsWithSecret: internalFunctionInteractsWithSecret, }); + + const functionParams = callingfnDefPath.node._newASTPointer.body.preStatements; + // console.log(functionParams); + // console.log(functionReferncedNode.node.returnParameters.parameters[0]._newASTPointer); + // if(!functionParams.includes(returnPara)){ + // callingfnDefPath.node._newASTPointer.parameters.parameters.push(functionReferncedNode.node.returnParameters.parameters[0]._newASTPointer); + // callingfnDefPath.node._newASTPointer.parameters.parameters[functionParams.length].declarationType = 'parameter'; + // callingfnDefPath.node._newASTPointer.parameters.parameters[functionParams.length].interactsWithSecret = true; + // } } else { newNode = buildNode('InternalFunctionCall', { name: node.expression.name, diff --git a/src/transformers/visitors/toCircuitVisitor.ts b/src/transformers/visitors/toCircuitVisitor.ts index f5bb50269..84c5e4d0e 100644 --- a/src/transformers/visitors/toCircuitVisitor.ts +++ b/src/transformers/visitors/toCircuitVisitor.ts @@ -1582,10 +1582,17 @@ const visitor = { state.circuitImport.push({isImported: 'false', modVars: modifiedVariables, callingFunction: callingfnDefPath.node.name}); let newNode: any; if(parent.nodeType === 'VariableDeclarationStatement') { + const returnPara = functionReferncedNode.node.returnParameters.parameters[0].name; newNode = buildNode('InternalFunctionCall', { - name: functionReferncedNode.node.returnParameters.parameters[0].name, + name: returnPara, internalFunctionInteractsWithSecret: internalFunctionInteractsWithSecret, // return }); + const functionParams = callingfnDefPath.node._newASTPointer.parameters.parameters.map(param => param.name); + if(!functionParams.includes(returnPara)){ + callingfnDefPath.node._newASTPointer.parameters.parameters.push(functionReferncedNode.node.returnParameters.parameters[0]._newASTPointer); + callingfnDefPath.node._newASTPointer.parameters.parameters[functionParams.length].declarationType = 'parameter'; + callingfnDefPath.node._newASTPointer.parameters.parameters[functionParams.length].interactsWithSecret = true; + } } else { newNode = buildNode('InternalFunctionCall', { @@ -1595,6 +1602,7 @@ if(parent.nodeType === 'VariableDeclarationStatement') { CircuitReturn:[], }); } + const fnNode = buildNode('InternalFunctionBoilerplate', { name: node.expression.name, internalFunctionInteractsWithSecret: internalFunctionInteractsWithSecret, diff --git a/test/contracts/internalFunctionCall-return2.zol b/test/contracts/internalFunctionCall-return2.zol new file mode 100644 index 000000000..c69f0f4b3 --- /dev/null +++ b/test/contracts/internalFunctionCall-return2.zol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: CC0 + +pragma solidity ^0.8.0; + +contract Assign { + + secret uint256 private a; + uint256 public b; + + function add( secret uint256 value, uint256 value1) public returns (uint256) { + a += value; + b += value1; + return b; + } + + function remove(secret uint256 value, uint256 value1) public { + uint256 c = add(value, value1); + a -= value + c; + } +} \ No newline at end of file From 0ae4fc3eefb0e911d3097f78046de75724b36745 Mon Sep 17 00:00:00 2001 From: Swati Rawal Date: Thu, 29 Aug 2024 08:06:13 +0100 Subject: [PATCH 06/17] chore: fixed secret call --- src/codeGenerators/circuit/zokrates/toCircuit.ts | 5 ++++- .../visitors/orchestrationInternalFunctionCallVisitor.ts | 6 ++++-- src/transformers/visitors/toCircuitVisitor.ts | 3 ++- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/codeGenerators/circuit/zokrates/toCircuit.ts b/src/codeGenerators/circuit/zokrates/toCircuit.ts index 39f9ab33e..e100c9bbf 100644 --- a/src/codeGenerators/circuit/zokrates/toCircuit.ts +++ b/src/codeGenerators/circuit/zokrates/toCircuit.ts @@ -160,7 +160,10 @@ function codeGenerator(node: any) { case 'VariableDeclarationStatement': { const declarations = node.declarations.map(codeGenerator).join(', '); if (!node.initialValue) return `${declarations} = ${node.declarations.map(n => n.typeName.name === 'bool' ? 'false' : 0)}`; - if(node.initialValue.nodeType === 'InternalFunctionCall') return `${declarations} = ${node.initialValue.name}`; + if(node.initialValue.nodeType === 'InternalFunctionCall'){ + if(!declarations) return ; + return `${declarations} = ${node.initialValue.name}`; + } const initialValue = codeGenerator(node.initialValue); return `${declarations} = ${initialValue}`; diff --git a/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts b/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts index 006af6366..c7cf92885 100644 --- a/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts +++ b/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts @@ -432,7 +432,7 @@ const internalCallVisitor = { }); }); node.privateStates = Object.assign(node.privateStates,generateProofNode.privateStates); - node.parameters = [...new Set([...node.parameters ,...generateProofNode.parameters])]; + node.parameters = [...new Set([...node.parameters ,...generateProofNode.parameters, ...state.returnPara])]; break; } case 'SendTransaction': { @@ -527,11 +527,13 @@ FunctionCall: { decNode.declarations[0].isAccessed = true; decNode.declarations[0].interactsWithSecret = true; callingfnDefPath.node._newASTPointer.body.preStatements.splice(1,0,decNode); - const returnPara = functionReferncedNode.node.returnParameters.parameters[0].name; + const returnPara = functionReferncedNode.node.returnParameters.parameters[0].name; newNode = buildNode('InternalFunctionCall', { name: returnPara, internalFunctionInteractsWithSecret: internalFunctionInteractsWithSecret, }); + console.log(parent) + parent.interactsWithSecret ? state.returnPara = returnPara : ' '; const functionParams = callingfnDefPath.node._newASTPointer.body.preStatements; // console.log(functionParams); diff --git a/src/transformers/visitors/toCircuitVisitor.ts b/src/transformers/visitors/toCircuitVisitor.ts index 84c5e4d0e..fe0e9df56 100644 --- a/src/transformers/visitors/toCircuitVisitor.ts +++ b/src/transformers/visitors/toCircuitVisitor.ts @@ -1587,12 +1587,13 @@ if(parent.nodeType === 'VariableDeclarationStatement') { name: returnPara, internalFunctionInteractsWithSecret: internalFunctionInteractsWithSecret, // return }); + if(parent._newASTPointer.declarations.length > 0){ const functionParams = callingfnDefPath.node._newASTPointer.parameters.parameters.map(param => param.name); if(!functionParams.includes(returnPara)){ callingfnDefPath.node._newASTPointer.parameters.parameters.push(functionReferncedNode.node.returnParameters.parameters[0]._newASTPointer); callingfnDefPath.node._newASTPointer.parameters.parameters[functionParams.length].declarationType = 'parameter'; callingfnDefPath.node._newASTPointer.parameters.parameters[functionParams.length].interactsWithSecret = true; - } + }} } else { newNode = buildNode('InternalFunctionCall', { From ad53bd51cae2941c9d522f200c3abf61f73e5cb3 Mon Sep 17 00:00:00 2001 From: Swati Rawal Date: Thu, 29 Aug 2024 10:43:47 +0100 Subject: [PATCH 07/17] chore: removed console logs --- .../contract/solidity/toContract.ts | 1 - .../orchestrationInternalFunctionCallVisitor.ts | 16 ++++------------ 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/src/codeGenerators/contract/solidity/toContract.ts b/src/codeGenerators/contract/solidity/toContract.ts index 42cce8663..472ddb087 100644 --- a/src/codeGenerators/contract/solidity/toContract.ts +++ b/src/codeGenerators/contract/solidity/toContract.ts @@ -140,7 +140,6 @@ function codeGenerator(node: any) { } case 'VariableDeclarationStatement': { - console.log(node); const declarations: string = node.declarations.map(codeGenerator).join(', '); if (declarations === '') return declarations; // when all are secret, we ignore them let initialValue; diff --git a/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts b/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts index c7cf92885..2b2a61188 100644 --- a/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts +++ b/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts @@ -432,7 +432,8 @@ const internalCallVisitor = { }); }); node.privateStates = Object.assign(node.privateStates,generateProofNode.privateStates); - node.parameters = [...new Set([...node.parameters ,...generateProofNode.parameters, ...state.returnPara])]; + node.parameters = [...new Set([...node.parameters ,...generateProofNode.parameters])]; + state.returnPara ? node.parameters = [...new Set([...node.parameters, ...state.returnPara])]: node.parameters; break; } case 'SendTransaction': { @@ -532,17 +533,8 @@ FunctionCall: { name: returnPara, internalFunctionInteractsWithSecret: internalFunctionInteractsWithSecret, }); - console.log(parent) - parent.interactsWithSecret ? state.returnPara = returnPara : ' '; - - const functionParams = callingfnDefPath.node._newASTPointer.body.preStatements; - // console.log(functionParams); - // console.log(functionReferncedNode.node.returnParameters.parameters[0]._newASTPointer); - // if(!functionParams.includes(returnPara)){ - // callingfnDefPath.node._newASTPointer.parameters.parameters.push(functionReferncedNode.node.returnParameters.parameters[0]._newASTPointer); - // callingfnDefPath.node._newASTPointer.parameters.parameters[functionParams.length].declarationType = 'parameter'; - // callingfnDefPath.node._newASTPointer.parameters.parameters[functionParams.length].interactsWithSecret = true; - // } + + parent._newASTPointer.interactsWithSecret ? state.returnPara = returnPara : ' '; } else { newNode = buildNode('InternalFunctionCall', { name: node.expression.name, From 5f59d82273c9e8f3ac9d69293e0d69089e8f3ae6 Mon Sep 17 00:00:00 2001 From: Swati Rawal Date: Thu, 29 Aug 2024 12:06:37 +0100 Subject: [PATCH 08/17] chore: fixed the node inputs --- .../visitors/circuitInternalFunctionCallVisitor.ts | 2 ++ .../orchestrationInternalFunctionCallVisitor.ts | 5 ++++- src/transformers/visitors/toCircuitVisitor.ts | 12 ++++++------ 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/transformers/visitors/circuitInternalFunctionCallVisitor.ts b/src/transformers/visitors/circuitInternalFunctionCallVisitor.ts index 44f5fb591..11cf48e91 100644 --- a/src/transformers/visitors/circuitInternalFunctionCallVisitor.ts +++ b/src/transformers/visitors/circuitInternalFunctionCallVisitor.ts @@ -114,6 +114,8 @@ const internalCallVisitor = { if(state.newStateArray[name][id].memberName) state.newParameterList.splice(nodeIndex,1); } + const params = state.newParameterList.map(node => node.name); + (state.paramNode && !(params.includes(state.paramNode.name))) ? state.newParameterList.push(state.paramNode) : state.newParameterList; } }) state.newReturnParameterList.forEach((node,nodeIndex) => { diff --git a/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts b/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts index 2b2a61188..4a4d00198 100644 --- a/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts +++ b/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts @@ -213,6 +213,9 @@ const internalCallVisitor = { file.nodes.forEach(childNode => { if(childNode.nodeType === 'FunctionDefinition') { childNode.parameters.modifiedStateVariables = joinWithoutDupes(childNode.parameters.modifiedStateVariables, state.newParametersList); + const modifiedNodes = childNode.parameters.modifiedStateVariables.map(node => node.name); + if(state.decNode && !(modifiedNodes.includes(state.decNode.declarations[0].name))) + childNode.body.preStatements.splice(1, 0, state.decNode); if(childNode.decrementedSecretStates) childNode.decrementedSecretStates = [...new Set([...childNode.decrementedSecretStates, ...newdecrementedSecretStates])]; childNode.body.preStatements.forEach(node => { @@ -527,7 +530,7 @@ FunctionCall: { decNode.declarations[0].declarationType = 'state'; decNode.declarations[0].isAccessed = true; decNode.declarations[0].interactsWithSecret = true; - callingfnDefPath.node._newASTPointer.body.preStatements.splice(1,0,decNode); + state.decNode = decNode; const returnPara = functionReferncedNode.node.returnParameters.parameters[0].name; newNode = buildNode('InternalFunctionCall', { name: returnPara, diff --git a/src/transformers/visitors/toCircuitVisitor.ts b/src/transformers/visitors/toCircuitVisitor.ts index fe0e9df56..be27dc0cf 100644 --- a/src/transformers/visitors/toCircuitVisitor.ts +++ b/src/transformers/visitors/toCircuitVisitor.ts @@ -1588,12 +1588,12 @@ if(parent.nodeType === 'VariableDeclarationStatement') { internalFunctionInteractsWithSecret: internalFunctionInteractsWithSecret, // return }); if(parent._newASTPointer.declarations.length > 0){ - const functionParams = callingfnDefPath.node._newASTPointer.parameters.parameters.map(param => param.name); - if(!functionParams.includes(returnPara)){ - callingfnDefPath.node._newASTPointer.parameters.parameters.push(functionReferncedNode.node.returnParameters.parameters[0]._newASTPointer); - callingfnDefPath.node._newASTPointer.parameters.parameters[functionParams.length].declarationType = 'parameter'; - callingfnDefPath.node._newASTPointer.parameters.parameters[functionParams.length].interactsWithSecret = true; - }} + // saving the return parameter to add in the circuits if it doesn't exist + state.paramNode = functionReferncedNode.node.returnParameters.parameters[0]._newASTPointer; + state.paramNode.declarationType = 'parameter'; + state.paramNode.interactsWithSecret = true; + +} } else { newNode = buildNode('InternalFunctionCall', { From 3ac2d07845477b136a9bc091e4c8dafac5eed13b Mon Sep 17 00:00:00 2001 From: Swati Rawal Date: Fri, 30 Aug 2024 16:16:52 +0100 Subject: [PATCH 09/17] chore: fix the public expression node --- .../circuitInternalFunctionCallVisitor.ts | 21 +++++++++++++-- ...rchestrationInternalFunctionCallVisitor.ts | 26 ++++++++++++++++--- src/transformers/visitors/toCircuitVisitor.ts | 13 +++++++--- 3 files changed, 51 insertions(+), 9 deletions(-) diff --git a/src/transformers/visitors/circuitInternalFunctionCallVisitor.ts b/src/transformers/visitors/circuitInternalFunctionCallVisitor.ts index 11cf48e91..31481e341 100644 --- a/src/transformers/visitors/circuitInternalFunctionCallVisitor.ts +++ b/src/transformers/visitors/circuitInternalFunctionCallVisitor.ts @@ -19,6 +19,8 @@ const reorderParameters = (parameterList: any) => { parameterList[index] = newParam; } } + if(param.name === newParam.name && param.nodeType === 'VariableDeclaration' && newParam.nodeType === 'Boilerplate') + parameterList.splice(index, 1); }); }); let newBPName: string; @@ -90,6 +92,7 @@ const internalCallVisitor = { node._newASTPointer.forEach(file => { if(file.fileName === name) { file.nodes.forEach(childNode => { + console.log(name); if(childNode.nodeType === 'FunctionDefinition'){ state.newParameterList = cloneDeep(childNode.parameters.parameters); state.newReturnParameterList = cloneDeep(childNode.returnParameters.parameters); @@ -114,8 +117,10 @@ const internalCallVisitor = { if(state.newStateArray[name][id].memberName) state.newParameterList.splice(nodeIndex,1); } - const params = state.newParameterList.map(node => node.name); - (state.paramNode && !(params.includes(state.paramNode.name))) ? state.newParameterList.push(state.paramNode) : state.newParameterList; + // const params = state.newParameterList.map(node => node.name); + // console.log(state.newParameterList); + // (state.paramNode && !(params.includes(state.paramNode.name))) ? state.newParameterList.push(state.paramNode) : state.newParameterList; + } }) state.newReturnParameterList.forEach((node,nodeIndex) => { @@ -197,6 +202,18 @@ const internalCallVisitor = { }) file.nodes.forEach(childNode => { if(childNode.nodeType === 'FunctionDefinition'){ + // console.log(state.functionArgs); + // console.log(childNode.parameters.parameters); + // console.log('=========================================='); + state.functionArgs.forEach(args => { + childNode.parameters.parameters.forEach((param, index) => { + if(state.isReturnInternalFunctionCall && param.name === args) + childNode.parameters.parameters.splice(index, 1); + }) + }) + //console.log(state.newParameterList); + + childNode.parameters.parameters = [...new Set([...childNode.parameters.parameters, ...state.newParameterList])]; reorderParameters(childNode.parameters.parameters); childNode.returnParameters.parameters = [...new Set([...childNode.returnParameters.parameters, ...state.newReturnParameterList])]; diff --git a/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts b/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts index 4a4d00198..d61b0c9b2 100644 --- a/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts +++ b/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts @@ -84,6 +84,8 @@ const internalCallVisitor = { }) state.newPreStatementList.splice(0,1); state.newStatementList = cloneDeep(childNode.body.statements); + // also adding the public expression node from the called function + if(state.expNode) state.newStatementList.push(state.expNode); const adjustNamesVisitor = (thisNode: any, state: any) => { if (thisNode.nodeType === 'VariableDeclaration'){ thisNode.name = thisNode.name.replace(state.oldStateName, state.newStateArray[name][state.currentIndex]); @@ -214,8 +216,9 @@ const internalCallVisitor = { if(childNode.nodeType === 'FunctionDefinition') { childNode.parameters.modifiedStateVariables = joinWithoutDupes(childNode.parameters.modifiedStateVariables, state.newParametersList); const modifiedNodes = childNode.parameters.modifiedStateVariables.map(node => node.name); + // if the function doesn't modifies the returned variable don't include it if(state.decNode && !(modifiedNodes.includes(state.decNode.declarations[0].name))) - childNode.body.preStatements.splice(1, 0, state.decNode); + childNode.body.preStatements.splice(1, 0, state.decNode); if(childNode.decrementedSecretStates) childNode.decrementedSecretStates = [...new Set([...childNode.decrementedSecretStates, ...newdecrementedSecretStates])]; childNode.body.preStatements.forEach(node => { @@ -271,7 +274,7 @@ const internalCallVisitor = { childNode.body.statements.forEach((node1, index1)=> { state.varNames = []; // check the node except the InternalFunctionCall node - if (!((node1.expression &&node1.expression?.nodeType === 'InternalFunctionCall') || (node1.initialValue && node1.initialValue?.nodeType === 'InternalFunctionCall'))){ + if (!((node1.expression && node1.expression?.nodeType === 'InternalFunctionCall') || (node1.initialValue && node1.initialValue?.nodeType === 'InternalFunctionCall'))){ traverseNodesFast(node1, findVarVisitor, state); } state.varNames.forEach((varName) => { @@ -324,6 +327,7 @@ const internalCallVisitor = { node.body.statements.forEach(kidNode => { if(kidNode.nodeType === 'ExpressionStatement' && kidNode.expression.name === state.internalFncName[index]) { if(kidNode.expression.operator) { + // If the internal function modifies the same state variable, we need to copy over the statements in the calling function const newExpressionNode = Object.assign(cloneDeep(kidNode.expression), statenode.expression); node.body.statements.push(newExpressionNode); } @@ -524,6 +528,7 @@ FunctionCall: { state.circuitImport.push('false'); let newNode; if(parent.nodeType === 'VariableDeclarationStatement') { + const decNode = buildNode('VariableDeclarationStatement') decNode.declarations.push(functionReferncedNode.node.returnParameters.parameters[0]._newASTPointer); decNode.interactsWithSecret = true; @@ -531,7 +536,22 @@ FunctionCall: { decNode.declarations[0].isAccessed = true; decNode.declarations[0].interactsWithSecret = true; state.decNode = decNode; - const returnPara = functionReferncedNode.node.returnParameters.parameters[0].name; + const returnPara = functionReferncedNode.node.returnParameters.parameters[0].name; + let includeExpressionNode = false; + // this functions checks if the parent node interact with secret in the calling function or not + callingfnDefIndicators[parent.declarations[0].id].interactsWith.forEach( node => { + if(node.key != 'arguments' && node.interactsWithSecret) + includeExpressionNode = true; + }) + functionReferncedNode.node.body.statements.forEach(exp => { + // If the return para interacts with public only in the internal function but with secret in calling function we need this expression in calling function + if(exp?.expression.leftHandSide?.name === returnPara && !exp.expression.leftHandSide.interactsWithSecret && includeExpressionNode){ + state.expNode = cloneDeep(exp._newASTPointer); + state.expNode.interactsWithSecret = 'true'; + } + + }) + newNode = buildNode('InternalFunctionCall', { name: returnPara, internalFunctionInteractsWithSecret: internalFunctionInteractsWithSecret, diff --git a/src/transformers/visitors/toCircuitVisitor.ts b/src/transformers/visitors/toCircuitVisitor.ts index be27dc0cf..43e0b93be 100644 --- a/src/transformers/visitors/toCircuitVisitor.ts +++ b/src/transformers/visitors/toCircuitVisitor.ts @@ -1582,17 +1582,22 @@ const visitor = { state.circuitImport.push({isImported: 'false', modVars: modifiedVariables, callingFunction: callingfnDefPath.node.name}); let newNode: any; if(parent.nodeType === 'VariableDeclarationStatement') { + state.isReturnInternalFunctionCall = true; + console.log(parent); + state.functionArgs = node.arguments.map(args => args.name); const returnPara = functionReferncedNode.node.returnParameters.parameters[0].name; newNode = buildNode('InternalFunctionCall', { name: returnPara, internalFunctionInteractsWithSecret: internalFunctionInteractsWithSecret, // return }); if(parent._newASTPointer.declarations.length > 0){ - // saving the return parameter to add in the circuits if it doesn't exist - state.paramNode = functionReferncedNode.node.returnParameters.parameters[0]._newASTPointer; - state.paramNode.declarationType = 'parameter'; - state.paramNode.interactsWithSecret = true; + const functionParams = callingfnDefPath.node._newASTPointer.parameters.parameters.map(param => param.name); + if(!functionParams.includes(returnPara)){ + callingfnDefPath.node._newASTPointer.parameters.parameters.push(functionReferncedNode.node.returnParameters.parameters[0]._newASTPointer); + callingfnDefPath.node._newASTPointer.parameters.parameters[functionParams.length].declarationType = 'parameter'; + callingfnDefPath.node._newASTPointer.parameters.parameters[functionParams.length].interactsWithSecret = true; + } } } else { From ab334fcb61da3021eeb21cfd5494bf010ad8d968 Mon Sep 17 00:00:00 2001 From: Swati Rawal Date: Tue, 3 Sep 2024 09:10:10 +0100 Subject: [PATCH 10/17] chore: fixed the return statement in node --- .../orchestration/nodejs/toOrchestration.ts | 5 + .../circuitInternalFunctionCallVisitor.ts | 17 +-- ...rchestrationInternalFunctionCallVisitor.ts | 39 +++++-- src/transformers/visitors/toCircuitVisitor.ts | 103 ++++++++++++++---- 4 files changed, 115 insertions(+), 49 deletions(-) diff --git a/src/codeGenerators/orchestration/nodejs/toOrchestration.ts b/src/codeGenerators/orchestration/nodejs/toOrchestration.ts index ccf35638a..bf3bff64e 100644 --- a/src/codeGenerators/orchestration/nodejs/toOrchestration.ts +++ b/src/codeGenerators/orchestration/nodejs/toOrchestration.ts @@ -92,6 +92,11 @@ export default function codeGenerator(node: any, options: any = {}): any { if (node.declarations[0].isStruct) return `\n let ${codeGenerator(node.declarations[0])} = {}; \n${codeGenerator(node.initialValue)};`; return `\nlet ${codeGenerator(node.initialValue)};`; } else if (node.declarations[0].isAccessed && !node.declarations[0].isSecret) { + const obj = {} + if(Object.keys(node.initialValue).length > 1) { + console.log('here'); + return `\nlet ${codeGenerator(node.declarations[0])} = generalise(${codeGenerator(node.initialValue)});`; + } else return `${getPublicValue(node.declarations[0])}` } else if (node.declarations[0].isAccessed) { return `${getAccessedValue(node.declarations[0].name)}`; diff --git a/src/transformers/visitors/circuitInternalFunctionCallVisitor.ts b/src/transformers/visitors/circuitInternalFunctionCallVisitor.ts index 31481e341..b8dc66271 100644 --- a/src/transformers/visitors/circuitInternalFunctionCallVisitor.ts +++ b/src/transformers/visitors/circuitInternalFunctionCallVisitor.ts @@ -117,10 +117,6 @@ const internalCallVisitor = { if(state.newStateArray[name][id].memberName) state.newParameterList.splice(nodeIndex,1); } - // const params = state.newParameterList.map(node => node.name); - // console.log(state.newParameterList); - // (state.paramNode && !(params.includes(state.paramNode.name))) ? state.newParameterList.push(state.paramNode) : state.newParameterList; - } }) state.newReturnParameterList.forEach((node,nodeIndex) => { @@ -202,18 +198,6 @@ const internalCallVisitor = { }) file.nodes.forEach(childNode => { if(childNode.nodeType === 'FunctionDefinition'){ - // console.log(state.functionArgs); - // console.log(childNode.parameters.parameters); - // console.log('=========================================='); - state.functionArgs.forEach(args => { - childNode.parameters.parameters.forEach((param, index) => { - if(state.isReturnInternalFunctionCall && param.name === args) - childNode.parameters.parameters.splice(index, 1); - }) - }) - //console.log(state.newParameterList); - - childNode.parameters.parameters = [...new Set([...childNode.parameters.parameters, ...state.newParameterList])]; reorderParameters(childNode.parameters.parameters); childNode.returnParameters.parameters = [...new Set([...childNode.returnParameters.parameters, ...state.newReturnParameterList])]; @@ -288,6 +272,7 @@ const internalCallVisitor = { } } }); + if(state.expNode) newExpressionList.push(state.expNode); childNode.body.preStatements.forEach(node => { if(node.isPartitioned){ commitmentValue = node.newCommitmentValue; diff --git a/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts b/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts index d61b0c9b2..28bc3a5cb 100644 --- a/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts +++ b/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts @@ -84,8 +84,6 @@ const internalCallVisitor = { }) state.newPreStatementList.splice(0,1); state.newStatementList = cloneDeep(childNode.body.statements); - // also adding the public expression node from the called function - if(state.expNode) state.newStatementList.push(state.expNode); const adjustNamesVisitor = (thisNode: any, state: any) => { if (thisNode.nodeType === 'VariableDeclaration'){ thisNode.name = thisNode.name.replace(state.oldStateName, state.newStateArray[name][state.currentIndex]); @@ -100,8 +98,9 @@ const internalCallVisitor = { state.currentIndex = index; traverseNodesFast(node, adjustNamesVisitor, state); } - }); + + if(state.expNode) state.newStatementList.push(state.expNode); state.newPostStatementList = cloneDeep(childNode.body.postStatements); state.newPostStatementList.forEach(node => { if(node.nodeType === 'MembershipWitness'){ @@ -273,8 +272,8 @@ const internalCallVisitor = { let newVarDecs = []; childNode.body.statements.forEach((node1, index1)=> { state.varNames = []; - // check the node except the InternalFunctionCall node - if (!((node1.expression && node1.expression?.nodeType === 'InternalFunctionCall') || (node1.initialValue && node1.initialValue?.nodeType === 'InternalFunctionCall'))){ + // check the node except the InternalFunctionCall node and new created public node + if (!((node1.expression && node1.expression?.nodeType === 'InternalFunctionCall') || (node1.initialValue && node1.initialValue?.nodeType === 'InternalFunctionCall') || node1.id === 0)){ traverseNodesFast(node1, findVarVisitor, state); } state.varNames.forEach((varName) => { @@ -517,7 +516,7 @@ FunctionCall: { } } else - isCircuit = true; + isCircuit = true; } } }); @@ -543,14 +542,34 @@ FunctionCall: { if(node.key != 'arguments' && node.interactsWithSecret) includeExpressionNode = true; }) + includeExpressionNode ? functionReferncedNode.node.body.statements.forEach(exp => { // If the return para interacts with public only in the internal function but with secret in calling function we need this expression in calling function - if(exp?.expression.leftHandSide?.name === returnPara && !exp.expression.leftHandSide.interactsWithSecret && includeExpressionNode){ - state.expNode = cloneDeep(exp._newASTPointer); - state.expNode.interactsWithSecret = 'true'; + if(exp?.expression.leftHandSide?.name === returnPara && !exp.expression.leftHandSide.interactsWithSecret){ + const newName =returnPara+'_1'; + const innerNode = buildNode('VariableDeclaration', { + name: newName, + isAccessed: true, + isSecret: false, + interactsWithSecret: true, // setting interact with secret true, as now it interacts with secret in the calling function + }); + const initNode = buildNode('BinaryOperation', { + leftExpression: exp._newASTPointer.expression.rightHandSide.leftExpression, + operator: exp._newASTPointer.expression.rightHandSide.operator, + rightExpression: exp._newASTPointer.expression.rightHandSide.rightExpression, + }); + state.expNode = buildNode('VariableDeclarationStatement',{ + declarations: [innerNode], + initialValue: initNode, + interactsWithSecret: true, + }) + newNode = buildNode('InternalFunctionCall', { + name: newName, + internalFunctionInteractsWithSecret: internalFunctionInteractsWithSecret, + }); } - }) + }) : newNode = buildNode('InternalFunctionCall', { name: returnPara, diff --git a/src/transformers/visitors/toCircuitVisitor.ts b/src/transformers/visitors/toCircuitVisitor.ts index 43e0b93be..a652f37cf 100644 --- a/src/transformers/visitors/toCircuitVisitor.ts +++ b/src/transformers/visitors/toCircuitVisitor.ts @@ -1575,30 +1575,87 @@ const visitor = { } } }); - state.circuitImport ??= []; - if(isCircuit) - state.circuitImport.push({isImported: 'true', modVars: modifiedVariables, callingFunction: callingfnDefPath.node.name}); - else - state.circuitImport.push({isImported: 'false', modVars: modifiedVariables, callingFunction: callingfnDefPath.node.name}); -let newNode: any; -if(parent.nodeType === 'VariableDeclarationStatement') { - state.isReturnInternalFunctionCall = true; - console.log(parent); - state.functionArgs = node.arguments.map(args => args.name); - const returnPara = functionReferncedNode.node.returnParameters.parameters[0].name; - newNode = buildNode('InternalFunctionCall', { - name: returnPara, - internalFunctionInteractsWithSecret: internalFunctionInteractsWithSecret, // return - }); - if(parent._newASTPointer.declarations.length > 0){ + state.circuitImport ??= []; + if(isCircuit) + state.circuitImport.push({isImported: 'true', modVars: modifiedVariables, callingFunction: callingfnDefPath.node.name}); + else + state.circuitImport.push({isImported: 'false', modVars: modifiedVariables, callingFunction: callingfnDefPath.node.name}); + let newNode: any; + if(parent.nodeType === 'VariableDeclarationStatement') { + state.isReturnInternalFunctionCall = true; + state.functionArgs = node.arguments.map(args => args.name); + const returnPara = functionReferncedNode.node.returnParameters.parameters[0].name; + newNode = buildNode('InternalFunctionCall', { + name: returnPara, + internalFunctionInteractsWithSecret: internalFunctionInteractsWithSecret, // return + }); + if(parent._newASTPointer.declarations.length > 0){ + const functionParams = callingfnDefPath.node._newASTPointer.parameters.parameters.map(param => param.name); + if(!functionParams.includes(returnPara)){ + callingfnDefPath.node._newASTPointer.parameters.parameters.push(functionReferncedNode.node.returnParameters.parameters[0]._newASTPointer); + callingfnDefPath.node._newASTPointer.parameters.parameters[functionParams.length].declarationType = 'parameter'; + callingfnDefPath.node._newASTPointer.parameters.parameters[functionParams.length].interactsWithSecret = true; + } + } + let includeExpressionNode = false; + // this functions checks if the parent node interact with secret in the calling function or not + callingfnDefIndicators[parent.declarations[0].id].interactsWith.forEach( node => { + if(node.key != 'arguments' && node.interactsWithSecret) + includeExpressionNode = true; + }) + includeExpressionNode ? + functionReferncedNode.node.body.statements.forEach(exp => { + // If the return para interacts with public only in the internal function but with secret in calling function we need this expression in calling function + if(exp?.expression.leftHandSide?.name === returnPara && !exp.expression.leftHandSide.interactsWithSecret){ + const newName =returnPara+'_1'; + const innerNode = buildNode('VariableDeclaration', { + name: newName, + isAccessed: true, + isSecret: false, + interactsWithSecret: true, // setting interact with secret true, as now it interacts with secret in the calling function + }); + innerNode.typeName.name = 'field'; + let initNode: any; + if(['+=', '-=', '*=', '/='].includes(exp.expression.operator)) { + initNode = buildNode('BinaryOperation', { + leftExpression: exp.expression.leftHandSide, + operator: exp.expression.operator.slice(0,-1), + rightExpression: exp.expression.rightHandSide, + }); + } + state.expNode = buildNode('VariableDeclarationStatement',{ + declarations: [innerNode], + initialValue: initNode, + interactsWithSecret: true, + }) + console.log(state.expNode); + + newNode = buildNode('InternalFunctionCall', { + name: newName, + internalFunctionInteractsWithSecret: internalFunctionInteractsWithSecret, + }); + // const decInnerNode = buildNode('VariableDeclaration', { + // name: `${node.name}_${num_modifiers}`, + // isAccessed: true, + // isSecret: false, + // interactsWithSecret: true, + // }); + // const initInnerNode = buildNode('Assignment', { + // leftHandSide: buildNode('Identifier', { name: `${node.name}_${num_modifiers}`, subType: 'generalNumber' }), + // operator: '=', + // rightHandSide: buildNode('Identifier', { name: `${node.name}`, subType: 'generalNumber' }) + // }); + // const newNode1 = buildNode('VariableDeclarationStatement', { + // declarations: [decInnerNode], + // initialValue: initInnerNode, + // interactsWithSecret: true, + // isModifiedDeclaration: true, + // }); + } + + }) : ''; + - const functionParams = callingfnDefPath.node._newASTPointer.parameters.parameters.map(param => param.name); - if(!functionParams.includes(returnPara)){ - callingfnDefPath.node._newASTPointer.parameters.parameters.push(functionReferncedNode.node.returnParameters.parameters[0]._newASTPointer); - callingfnDefPath.node._newASTPointer.parameters.parameters[functionParams.length].declarationType = 'parameter'; - callingfnDefPath.node._newASTPointer.parameters.parameters[functionParams.length].interactsWithSecret = true; - } -} } else { newNode = buildNode('InternalFunctionCall', { From fba991a5a2ef4eb1430cae529b6e324694beb4bb Mon Sep 17 00:00:00 2001 From: Swati Rawal Date: Tue, 3 Sep 2024 16:23:27 +0100 Subject: [PATCH 11/17] chore: added code for secret function call --- .../circuit/zokrates/toCircuit.ts | 4 +- .../orchestration/nodejs/toOrchestration.ts | 1 - .../circuitInternalFunctionCallVisitor.ts | 5 +- src/transformers/visitors/toCircuitVisitor.ts | 61 ++++--------------- 4 files changed, 18 insertions(+), 53 deletions(-) diff --git a/src/codeGenerators/circuit/zokrates/toCircuit.ts b/src/codeGenerators/circuit/zokrates/toCircuit.ts index e100c9bbf..70c6e6c8e 100644 --- a/src/codeGenerators/circuit/zokrates/toCircuit.ts +++ b/src/codeGenerators/circuit/zokrates/toCircuit.ts @@ -161,8 +161,8 @@ function codeGenerator(node: any) { const declarations = node.declarations.map(codeGenerator).join(', '); if (!node.initialValue) return `${declarations} = ${node.declarations.map(n => n.typeName.name === 'bool' ? 'false' : 0)}`; if(node.initialValue.nodeType === 'InternalFunctionCall'){ - if(!declarations) return ; - return `${declarations} = ${node.initialValue.name}`; + if(!declarations) return ; + return `${declarations} = ${codeGenerator(node.initialValue.expression)}`; } const initialValue = codeGenerator(node.initialValue); diff --git a/src/codeGenerators/orchestration/nodejs/toOrchestration.ts b/src/codeGenerators/orchestration/nodejs/toOrchestration.ts index bf3bff64e..97a8b5bf5 100644 --- a/src/codeGenerators/orchestration/nodejs/toOrchestration.ts +++ b/src/codeGenerators/orchestration/nodejs/toOrchestration.ts @@ -94,7 +94,6 @@ export default function codeGenerator(node: any, options: any = {}): any { } else if (node.declarations[0].isAccessed && !node.declarations[0].isSecret) { const obj = {} if(Object.keys(node.initialValue).length > 1) { - console.log('here'); return `\nlet ${codeGenerator(node.declarations[0])} = generalise(${codeGenerator(node.initialValue)});`; } else return `${getPublicValue(node.declarations[0])}` diff --git a/src/transformers/visitors/circuitInternalFunctionCallVisitor.ts b/src/transformers/visitors/circuitInternalFunctionCallVisitor.ts index b8dc66271..99c32fdb9 100644 --- a/src/transformers/visitors/circuitInternalFunctionCallVisitor.ts +++ b/src/transformers/visitors/circuitInternalFunctionCallVisitor.ts @@ -92,7 +92,6 @@ const internalCallVisitor = { node._newASTPointer.forEach(file => { if(file.fileName === name) { file.nodes.forEach(childNode => { - console.log(name); if(childNode.nodeType === 'FunctionDefinition'){ state.newParameterList = cloneDeep(childNode.parameters.parameters); state.newReturnParameterList = cloneDeep(childNode.returnParameters.parameters); @@ -272,7 +271,7 @@ const internalCallVisitor = { } } }); - if(state.expNode) newExpressionList.push(state.expNode); + // if(state.expNode) newExpressionList.push(state.expNode); childNode.body.preStatements.forEach(node => { if(node.isPartitioned){ commitmentValue = node.newCommitmentValue; @@ -293,6 +292,8 @@ const internalCallVisitor = { file.nodes.forEach(childNode => { if(childNode.nodeType === 'FunctionDefinition') { childNode.body.statements.forEach(node => { + if(node.initialValue?.nodeType === 'InternalFunctionCall' && state.initNode) + node.initialValue.expression = state.initNode; if(node.nodeType==='BoilerplateStatement'){ callingFncbpType = node.bpType; } diff --git a/src/transformers/visitors/toCircuitVisitor.ts b/src/transformers/visitors/toCircuitVisitor.ts index a652f37cf..7b9f620ce 100644 --- a/src/transformers/visitors/toCircuitVisitor.ts +++ b/src/transformers/visitors/toCircuitVisitor.ts @@ -1603,18 +1603,9 @@ const visitor = { if(node.key != 'arguments' && node.interactsWithSecret) includeExpressionNode = true; }) - includeExpressionNode ? functionReferncedNode.node.body.statements.forEach(exp => { // If the return para interacts with public only in the internal function but with secret in calling function we need this expression in calling function if(exp?.expression.leftHandSide?.name === returnPara && !exp.expression.leftHandSide.interactsWithSecret){ - const newName =returnPara+'_1'; - const innerNode = buildNode('VariableDeclaration', { - name: newName, - isAccessed: true, - isSecret: false, - interactsWithSecret: true, // setting interact with secret true, as now it interacts with secret in the calling function - }); - innerNode.typeName.name = 'field'; let initNode: any; if(['+=', '-=', '*=', '/='].includes(exp.expression.operator)) { initNode = buildNode('BinaryOperation', { @@ -1623,49 +1614,23 @@ const visitor = { rightExpression: exp.expression.rightHandSide, }); } - state.expNode = buildNode('VariableDeclarationStatement',{ - declarations: [innerNode], - initialValue: initNode, - interactsWithSecret: true, - }) - console.log(state.expNode); - newNode = buildNode('InternalFunctionCall', { - name: newName, + name: returnPara, internalFunctionInteractsWithSecret: internalFunctionInteractsWithSecret, }); - // const decInnerNode = buildNode('VariableDeclaration', { - // name: `${node.name}_${num_modifiers}`, - // isAccessed: true, - // isSecret: false, - // interactsWithSecret: true, - // }); - // const initInnerNode = buildNode('Assignment', { - // leftHandSide: buildNode('Identifier', { name: `${node.name}_${num_modifiers}`, subType: 'generalNumber' }), - // operator: '=', - // rightHandSide: buildNode('Identifier', { name: `${node.name}`, subType: 'generalNumber' }) - // }); - // const newNode1 = buildNode('VariableDeclarationStatement', { - // declarations: [decInnerNode], - // initialValue: initInnerNode, - // interactsWithSecret: true, - // isModifiedDeclaration: true, - // }); - } + includeExpressionNode? state.initNode = initNode : ''; + } - }) : ''; - - -} else - { - newNode = buildNode('InternalFunctionCall', { - name: node.expression.name, - internalFunctionInteractsWithSecret: internalFunctionInteractsWithSecret, - CircuitArguments: [], - CircuitReturn:[], - }); - } - + }) + } else + { + newNode = buildNode('InternalFunctionCall', { + name: node.expression.name, + internalFunctionInteractsWithSecret: internalFunctionInteractsWithSecret, + CircuitArguments: [], + CircuitReturn:[], + }); + } const fnNode = buildNode('InternalFunctionBoilerplate', { name: node.expression.name, internalFunctionInteractsWithSecret: internalFunctionInteractsWithSecret, From c726e137827d2709a5dc79e49ee65395d33d4703 Mon Sep 17 00:00:00 2001 From: Swati Rawal Date: Tue, 3 Sep 2024 16:53:33 +0100 Subject: [PATCH 12/17] chore: fixed the return call --- src/codeGenerators/circuit/zokrates/toCircuit.ts | 2 ++ src/transformers/visitors/toCircuitVisitor.ts | 7 ++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/codeGenerators/circuit/zokrates/toCircuit.ts b/src/codeGenerators/circuit/zokrates/toCircuit.ts index 70c6e6c8e..af7717d7f 100644 --- a/src/codeGenerators/circuit/zokrates/toCircuit.ts +++ b/src/codeGenerators/circuit/zokrates/toCircuit.ts @@ -162,7 +162,9 @@ function codeGenerator(node: any) { if (!node.initialValue) return `${declarations} = ${node.declarations.map(n => n.typeName.name === 'bool' ? 'false' : 0)}`; if(node.initialValue.nodeType === 'InternalFunctionCall'){ if(!declarations) return ; + if(node.initialValue.expression.nodeType === 'BinaryOperation') return `${declarations} = ${codeGenerator(node.initialValue.expression)}`; + return `${declarations} = ${node.initialValue.name}`; } const initialValue = codeGenerator(node.initialValue); diff --git a/src/transformers/visitors/toCircuitVisitor.ts b/src/transformers/visitors/toCircuitVisitor.ts index 7b9f620ce..5504605da 100644 --- a/src/transformers/visitors/toCircuitVisitor.ts +++ b/src/transformers/visitors/toCircuitVisitor.ts @@ -1613,7 +1613,12 @@ const visitor = { operator: exp.expression.operator.slice(0,-1), rightExpression: exp.expression.rightHandSide, }); - } + } else + initNode = buildNode('BinaryOperation', { + leftExpression: exp.expression.rightHandSide.leftExpression, + operator: exp.expression.rightHandSide.operator, + rightExpression: exp.expression.rightHandSide.rightExpression, + }); newNode = buildNode('InternalFunctionCall', { name: returnPara, internalFunctionInteractsWithSecret: internalFunctionInteractsWithSecret, From 8d52c8d99599bb1bf25f6a312354a2c354d51108 Mon Sep 17 00:00:00 2001 From: Swati Rawal Date: Wed, 4 Sep 2024 09:01:30 +0100 Subject: [PATCH 13/17] chore: fixed the contracts --- test/contracts/internalFunctionCall-return.zol | 2 +- test/contracts/internalFunctionCall-return2.zol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/contracts/internalFunctionCall-return.zol b/test/contracts/internalFunctionCall-return.zol index 6f806001a..0bcec9654 100644 --- a/test/contracts/internalFunctionCall-return.zol +++ b/test/contracts/internalFunctionCall-return.zol @@ -16,6 +16,6 @@ contract Assign { function remove(secret uint256 value, uint256 value1) public { uint256 c = add(value, value1); b += c + 1; - a -= value + value1; + a -= value1; } } \ No newline at end of file diff --git a/test/contracts/internalFunctionCall-return2.zol b/test/contracts/internalFunctionCall-return2.zol index c69f0f4b3..9ca8f5064 100644 --- a/test/contracts/internalFunctionCall-return2.zol +++ b/test/contracts/internalFunctionCall-return2.zol @@ -15,6 +15,6 @@ contract Assign { function remove(secret uint256 value, uint256 value1) public { uint256 c = add(value, value1); - a -= value + c; + a -= c; } } \ No newline at end of file From eba199032620f526612a8a41c684e610b83a1f4f Mon Sep 17 00:00:00 2001 From: Swati Rawal Date: Tue, 10 Sep 2024 10:04:23 +0100 Subject: [PATCH 14/17] chore: fixed for multiple function calls --- .../circuit/zokrates/toCircuit.ts | 4 +- .../orchestration/nodejs/toOrchestration.ts | 10 ++-- .../circuitInternalFunctionCallVisitor.ts | 18 ++++-- ...rchestrationInternalFunctionCallVisitor.ts | 59 ++++++++----------- src/transformers/visitors/toCircuitVisitor.ts | 5 +- .../internalFunctionCall-Return3.zol | 28 +++++++++ .../internalFunctionCall-Return4.zol | 28 +++++++++ .../internalFunctionCall-return2.zol | 9 ++- 8 files changed, 112 insertions(+), 49 deletions(-) create mode 100644 test/contracts/internalFunctionCall-Return3.zol create mode 100644 test/contracts/internalFunctionCall-Return4.zol diff --git a/src/codeGenerators/circuit/zokrates/toCircuit.ts b/src/codeGenerators/circuit/zokrates/toCircuit.ts index af7717d7f..d6c86ad50 100644 --- a/src/codeGenerators/circuit/zokrates/toCircuit.ts +++ b/src/codeGenerators/circuit/zokrates/toCircuit.ts @@ -160,9 +160,9 @@ function codeGenerator(node: any) { case 'VariableDeclarationStatement': { const declarations = node.declarations.map(codeGenerator).join(', '); if (!node.initialValue) return `${declarations} = ${node.declarations.map(n => n.typeName.name === 'bool' ? 'false' : 0)}`; - if(node.initialValue.nodeType === 'InternalFunctionCall'){ + if(node.initialValue?.nodeType === 'InternalFunctionCall'){ if(!declarations) return ; - if(node.initialValue.expression.nodeType === 'BinaryOperation') + if(node.initialValue?.expression?.nodeType === 'BinaryOperation') return `${declarations} = ${codeGenerator(node.initialValue.expression)}`; return `${declarations} = ${node.initialValue.name}`; } diff --git a/src/codeGenerators/orchestration/nodejs/toOrchestration.ts b/src/codeGenerators/orchestration/nodejs/toOrchestration.ts index 928cbd000..5f455f329 100644 --- a/src/codeGenerators/orchestration/nodejs/toOrchestration.ts +++ b/src/codeGenerators/orchestration/nodejs/toOrchestration.ts @@ -91,10 +91,6 @@ export default function codeGenerator(node: any, options: any = {}): any { if (node.declarations[0].isStruct) return `\n let ${codeGenerator(node.declarations[0])} = {}; \n${codeGenerator(node.initialValue)};`; return `\nlet ${codeGenerator(node.initialValue)};`; } else if (node.declarations[0].isAccessed && !node.declarations[0].isSecret) { - const obj = {} - if(Object.keys(node.initialValue).length > 1) { - return `\nlet ${codeGenerator(node.declarations[0])} = generalise(${codeGenerator(node.initialValue)});`; - } else return `${getPublicValue(node.declarations[0])}` } else if (node.declarations[0].isAccessed) { return `${getAccessedValue(node.declarations[0].name)}`; @@ -111,7 +107,11 @@ export default function codeGenerator(node: any, options: any = {}): any { if (!node.initialValue.nodeType) return `\nlet ${codeGenerator(node.declarations[0])};` // local var dec if (node.initialValue.nodeType === 'Literal' && node.isInitializationExpression) return `\nlet ${codeGenerator(node.declarations[0])} = ${codeGenerator(node.initialValue)};`; - if(node.initialValue.nodeType === 'InternalFunctionCall') return `\nlet ${codeGenerator(node.declarations[0])} = generalise(${node.initialValue.name}.integer);`; + if(node.initialValue.nodeType === 'InternalFunctionCall'){ + if(node.initialValue?.expression?.nodeType === 'BinaryOperation') + return `\nlet ${codeGenerator(node.declarations[0])} = ${codeGenerator(node.initialValue.expression)};`; + return `\nlet ${codeGenerator(node.declarations[0])} = ${node.initialValue.name};`; + } return `\nlet ${codeGenerator(node.declarations[0])} = generalise(${codeGenerator(node.initialValue)});`; } return `\nlet ${codeGenerator(node.initialValue)};`; diff --git a/src/transformers/visitors/circuitInternalFunctionCallVisitor.ts b/src/transformers/visitors/circuitInternalFunctionCallVisitor.ts index 99c32fdb9..c4299e2c5 100644 --- a/src/transformers/visitors/circuitInternalFunctionCallVisitor.ts +++ b/src/transformers/visitors/circuitInternalFunctionCallVisitor.ts @@ -7,6 +7,7 @@ import buildNode from '../../types/orchestration-types.js' // We need to ensure that parameters appear in the same order as in the .mjs file if the same state variables are used in multiple function calls. // All parameters relating to the same state variable should be grouped together. const reorderParameters = (parameterList: any) => { + let deletedIndexes = []; parameterList.forEach((param, index) => { parameterList.forEach((newParam, newIndex) => { if (param.name === newParam.name && param.bpType === 'nullification' && newParam.bpType === 'nullification') { @@ -19,10 +20,13 @@ const reorderParameters = (parameterList: any) => { parameterList[index] = newParam; } } - if(param.name === newParam.name && param.nodeType === 'VariableDeclaration' && newParam.nodeType === 'Boilerplate') - parameterList.splice(index, 1); + if(param.name === newParam.name && param.nodeType === 'VariableDeclaration' && newParam.nodeType === 'Boilerplate'){ + !deletedIndexes.includes(index)? deletedIndexes.push(index) : deletedIndexes; + } + }); }); + deletedIndexes.forEach(index => parameterList.splice(index, 1)); let newBPName: string; let currentIndex: number; let newCommitment = {}; @@ -61,6 +65,7 @@ const reorderParameters = (parameterList: any) => { elementsToAdd.forEach((element) => { parameterList.splice(element.NewIndex, 0, element.element); }); + } @@ -271,7 +276,6 @@ const internalCallVisitor = { } } }); - // if(state.expNode) newExpressionList.push(state.expNode); childNode.body.preStatements.forEach(node => { if(node.isPartitioned){ commitmentValue = node.newCommitmentValue; @@ -291,9 +295,11 @@ const internalCallVisitor = { if(file.fileName === callingFncName) { file.nodes.forEach(childNode => { if(childNode.nodeType === 'FunctionDefinition') { - childNode.body.statements.forEach(node => { - if(node.initialValue?.nodeType === 'InternalFunctionCall' && state.initNode) - node.initialValue.expression = state.initNode; + childNode.body.statements.forEach((node) => { + if(node.initialValue?.nodeType === 'InternalFunctionCall' && state.initNode) { + node.initialValue.expression = state.initNode[ node.initialValue.name ]; + } + if(node.nodeType==='BoilerplateStatement'){ callingFncbpType = node.bpType; } diff --git a/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts b/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts index 28bc3a5cb..9d8cdf475 100644 --- a/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts +++ b/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts @@ -215,9 +215,13 @@ const internalCallVisitor = { if(childNode.nodeType === 'FunctionDefinition') { childNode.parameters.modifiedStateVariables = joinWithoutDupes(childNode.parameters.modifiedStateVariables, state.newParametersList); const modifiedNodes = childNode.parameters.modifiedStateVariables.map(node => node.name); - // if the function doesn't modifies the returned variable don't include it - if(state.decNode && !(modifiedNodes.includes(state.decNode.declarations[0].name))) - childNode.body.preStatements.splice(1, 0, state.decNode); + const decNode = childNode.body.preStatements.filter(node => node.nodeType === 'VariableDeclarationStatement'); + !JSON.stringify(decNode).includes(JSON.stringify(state.decNode)) ? + state.decNode?.forEach((decNode, decIndex) => { + // if the function doesn't modifies the returned variable don't include it + if(state.decNode && !(modifiedNodes.includes(decNode.declarations[0].name))) + childNode.body.preStatements.splice(decIndex+1, 0, decNode); + }): ''; if(childNode.decrementedSecretStates) childNode.decrementedSecretStates = [...new Set([...childNode.decrementedSecretStates, ...newdecrementedSecretStates])]; childNode.body.preStatements.forEach(node => { @@ -272,7 +276,7 @@ const internalCallVisitor = { let newVarDecs = []; childNode.body.statements.forEach((node1, index1)=> { state.varNames = []; - // check the node except the InternalFunctionCall node and new created public node + // check the node except the InternalFunctionCall node and new created public node with id = 0 as we created it if (!((node1.expression && node1.expression?.nodeType === 'InternalFunctionCall') || (node1.initialValue && node1.initialValue?.nodeType === 'InternalFunctionCall') || node1.id === 0)){ traverseNodesFast(node1, findVarVisitor, state); } @@ -527,14 +531,17 @@ FunctionCall: { state.circuitImport.push('false'); let newNode; if(parent.nodeType === 'VariableDeclarationStatement') { - + if(!functionReferncedNode.node.returnParameters.parameters[0]._newASTPointer.isSecret) { const decNode = buildNode('VariableDeclarationStatement') decNode.declarations.push(functionReferncedNode.node.returnParameters.parameters[0]._newASTPointer); decNode.interactsWithSecret = true; decNode.declarations[0].declarationType = 'state'; decNode.declarations[0].isAccessed = true; decNode.declarations[0].interactsWithSecret = true; - state.decNode = decNode; + state.decNode ??= []; + const decNodeNames = state.decNode.map(node => node.declarations[0].name); + decNodeNames.includes(decNode.declarations[0].name) ? state.decNode : state.decNode.push(decNode); + } const returnPara = functionReferncedNode.node.returnParameters.parameters[0].name; let includeExpressionNode = false; // this functions checks if the parent node interact with secret in the calling function or not @@ -542,41 +549,25 @@ FunctionCall: { if(node.key != 'arguments' && node.interactsWithSecret) includeExpressionNode = true; }) - includeExpressionNode ? functionReferncedNode.node.body.statements.forEach(exp => { // If the return para interacts with public only in the internal function but with secret in calling function we need this expression in calling function if(exp?.expression.leftHandSide?.name === returnPara && !exp.expression.leftHandSide.interactsWithSecret){ - const newName =returnPara+'_1'; - const innerNode = buildNode('VariableDeclaration', { - name: newName, - isAccessed: true, - isSecret: false, - interactsWithSecret: true, // setting interact with secret true, as now it interacts with secret in the calling function - }); - const initNode = buildNode('BinaryOperation', { + state.initNode = buildNode('BinaryOperation', { leftExpression: exp._newASTPointer.expression.rightHandSide.leftExpression, operator: exp._newASTPointer.expression.rightHandSide.operator, rightExpression: exp._newASTPointer.expression.rightHandSide.rightExpression, }); - state.expNode = buildNode('VariableDeclarationStatement',{ - declarations: [innerNode], - initialValue: initNode, - interactsWithSecret: true, - }) - newNode = buildNode('InternalFunctionCall', { - name: newName, - internalFunctionInteractsWithSecret: internalFunctionInteractsWithSecret, - }); - } - - }) : - - newNode = buildNode('InternalFunctionCall', { - name: returnPara, - internalFunctionInteractsWithSecret: internalFunctionInteractsWithSecret, - }); - - parent._newASTPointer.interactsWithSecret ? state.returnPara = returnPara : ' '; + } + newNode = buildNode('InternalFunctionCall', { + name: returnPara, + internalFunctionInteractsWithSecret: internalFunctionInteractsWithSecret, + }); + if(includeExpressionNode && state.initNode) { + newNode.expression = state.initNode; + } + + parent._newASTPointer.interactsWithSecret ? state.returnPara = returnPara : ' '; + }) } else { newNode = buildNode('InternalFunctionCall', { name: node.expression.name, diff --git a/src/transformers/visitors/toCircuitVisitor.ts b/src/transformers/visitors/toCircuitVisitor.ts index 5084e1221..0fa2d06fc 100644 --- a/src/transformers/visitors/toCircuitVisitor.ts +++ b/src/transformers/visitors/toCircuitVisitor.ts @@ -1623,7 +1623,10 @@ const visitor = { name: returnPara, internalFunctionInteractsWithSecret: internalFunctionInteractsWithSecret, }); - includeExpressionNode? state.initNode = initNode : ''; + if(includeExpressionNode) { + state.initNode ??= []; + state.initNode[ returnPara ] = initNode; + } } }) diff --git a/test/contracts/internalFunctionCall-Return3.zol b/test/contracts/internalFunctionCall-Return3.zol new file mode 100644 index 000000000..a9a38992b --- /dev/null +++ b/test/contracts/internalFunctionCall-Return3.zol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: CC0 + +pragma solidity ^0.8.0; + +contract Assign { + + secret uint256 private a; + secret uint256 private b; + uint256 public m; + + function add( secret uint256 value, uint256 value1) public returns (uint256) { + a += value; + b += value1; + return b; + } + + function add1( secret uint256 value, uint256 value1) public returns (uint256) { + a += value; + m += value1 + 2; + return m; + } + + function remove(secret uint256 value, uint256 value1) public { + uint256 c = add(value, value1); + uint256 d = add1(value, value1); + a -= c + d ; + } +} \ No newline at end of file diff --git a/test/contracts/internalFunctionCall-Return4.zol b/test/contracts/internalFunctionCall-Return4.zol new file mode 100644 index 000000000..94484d289 --- /dev/null +++ b/test/contracts/internalFunctionCall-Return4.zol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: CC0 + +pragma solidity ^0.8.0; + +contract Assign { + + secret uint256 private a; + uint256 public b; + uint256 public m; + + function add( secret uint256 value, uint256 value1) public returns (uint256) { + a += value; + b += value1; + return b; + } + + function add1( secret uint256 value, uint256 value1) public returns (uint256) { + a += value; + m += value1 + 2; + return m; + } + + function remove(secret uint256 value, uint256 value1) public { + uint256 c = add(value, value1); + uint256 d = add1(value, value1); + a -= c + d ; + } +} \ No newline at end of file diff --git a/test/contracts/internalFunctionCall-return2.zol b/test/contracts/internalFunctionCall-return2.zol index 9ca8f5064..07bb82a75 100644 --- a/test/contracts/internalFunctionCall-return2.zol +++ b/test/contracts/internalFunctionCall-return2.zol @@ -13,8 +13,15 @@ contract Assign { return b; } + function add1( secret uint256 value, uint256 value1) public returns (uint256) { + a += value; + b += value1 + 2; + return b; + } + function remove(secret uint256 value, uint256 value1) public { uint256 c = add(value, value1); - a -= c; + uint256 d = add1(value, value1); + a -= c + d ; } } \ No newline at end of file From 7aa2f9902d80c46c1f302f9883b1bd90619a9555 Mon Sep 17 00:00:00 2001 From: Swati Rawal Date: Tue, 10 Sep 2024 10:15:44 +0100 Subject: [PATCH 15/17] chore: added a comment --- .../visitors/orchestrationInternalFunctionCallVisitor.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts b/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts index 9d8cdf475..2a38cb7c3 100644 --- a/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts +++ b/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts @@ -316,6 +316,7 @@ const internalCallVisitor = { childNode.body.statements[id-1] = statenode; node.body.statements.forEach(kidNode =>{ if(kidNode.nodeType === 'ExpressionStatement'&& kidNode.expression.name === state.internalFncName[index]) { + //When Internal function is inside for-loop, it exit under Expression Statement, we replace the function call with expression from the called function if (kidNode.expression.operator) { const newExpressionNode = Object.assign(cloneDeep(kidNode.expression), statenode.initialValue); node.body.statements.push(newExpressionNode); From da77414348e1c995978be1800e395aed2f72ff5b Mon Sep 17 00:00:00 2001 From: Swati Rawal Date: Fri, 13 Sep 2024 11:31:36 +0100 Subject: [PATCH 16/17] chore: added few fixes --- .../circuitInternalFunctionCallVisitor.ts | 6 +++- ...rchestrationInternalFunctionCallVisitor.ts | 36 +++++++++++++++---- test/contracts/for-InternalFunctionCall.zol | 4 +-- 3 files changed, 37 insertions(+), 9 deletions(-) diff --git a/src/transformers/visitors/circuitInternalFunctionCallVisitor.ts b/src/transformers/visitors/circuitInternalFunctionCallVisitor.ts index c4299e2c5..c8e1bcba9 100644 --- a/src/transformers/visitors/circuitInternalFunctionCallVisitor.ts +++ b/src/transformers/visitors/circuitInternalFunctionCallVisitor.ts @@ -26,7 +26,11 @@ const reorderParameters = (parameterList: any) => { }); }); - deletedIndexes.forEach(index => parameterList.splice(index, 1)); + // sort the array in descending array so that we delete the correct elements + deletedIndexes = deletedIndexes.slice().sort((a, b) => b - a); + deletedIndexes.forEach(index => { + parameterList.splice(index, 1) + }); let newBPName: string; let currentIndex: number; let newCommitment = {}; diff --git a/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts b/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts index 2a38cb7c3..9b0d67e8c 100644 --- a/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts +++ b/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts @@ -98,9 +98,7 @@ const internalCallVisitor = { state.currentIndex = index; traverseNodesFast(node, adjustNamesVisitor, state); } - }); - - if(state.expNode) state.newStatementList.push(state.expNode); + }); state.newPostStatementList = cloneDeep(childNode.body.postStatements); state.newPostStatementList.forEach(node => { if(node.nodeType === 'MembershipWitness'){ @@ -215,8 +213,8 @@ const internalCallVisitor = { if(childNode.nodeType === 'FunctionDefinition') { childNode.parameters.modifiedStateVariables = joinWithoutDupes(childNode.parameters.modifiedStateVariables, state.newParametersList); const modifiedNodes = childNode.parameters.modifiedStateVariables.map(node => node.name); - const decNode = childNode.body.preStatements.filter(node => node.nodeType === 'VariableDeclarationStatement'); - !JSON.stringify(decNode).includes(JSON.stringify(state.decNode)) ? + const declarationNode = childNode.body.preStatements.filter(node => node.nodeType === 'VariableDeclarationStatement'); + !JSON.stringify(declarationNode).includes(JSON.stringify(state.decNode)) ? state.decNode?.forEach((decNode, decIndex) => { // if the function doesn't modifies the returned variable don't include it if(state.decNode && !(modifiedNodes.includes(decNode.declarations[0].name))) @@ -318,9 +316,35 @@ const internalCallVisitor = { if(kidNode.nodeType === 'ExpressionStatement'&& kidNode.expression.name === state.internalFncName[index]) { //When Internal function is inside for-loop, it exit under Expression Statement, we replace the function call with expression from the called function if (kidNode.expression.operator) { + // for statement like + /* + for (statement) { + a += internalFuncCall(); + } here, kidNode will look like + expression: { + nodeType: 'Assignment', + name: 'add', + internalFunctionInteractsWithSecret: true, + operator: '+=', + leftHandSide: { nodeType: 'Identifier', name: 'a', subType: 'uint256' }, + }, and we need to get the other expression from the other function here. + */ const newExpressionNode = Object.assign(cloneDeep(kidNode.expression), statenode.initialValue); node.body.statements.push(newExpressionNode); } else { + // for statement like + /* + for (statement) { + internalFuncCall(); + } here, kidNode will look like + expression: { + expression: { + nodeType: 'InternalFunctionCall', + name: 'add', + internalFunctionInteractsWithSecret: true + }, + and we need to get the other expression from the other function here. + */ Object.assign(kidNode.expression, statenode.initialValue); } } @@ -567,7 +591,7 @@ FunctionCall: { newNode.expression = state.initNode; } - parent._newASTPointer.interactsWithSecret ? state.returnPara = returnPara : ' '; + parent._newASTPointer.interactsWithSecret ? state.returnPara.push(returnPara) : ' '; }) } else { newNode = buildNode('InternalFunctionCall', { diff --git a/test/contracts/for-InternalFunctionCall.zol b/test/contracts/for-InternalFunctionCall.zol index b780e5431..43d4c5efa 100644 --- a/test/contracts/for-InternalFunctionCall.zol +++ b/test/contracts/for-InternalFunctionCall.zol @@ -5,7 +5,7 @@ pragma solidity ^0.8.0; contract Assign { secret uint256 private a; - secret uint256 private b; + function remove(secret uint256 value) public { a -= value; uint k; @@ -15,6 +15,6 @@ contract Assign { } function add(secret uint256 value) public { known a += value; - b += 1; + a += 1; } } From 5b5e461938741b8bd776dec80165d4fbedaef584 Mon Sep 17 00:00:00 2001 From: Swati Rawal Date: Fri, 13 Sep 2024 12:02:52 +0100 Subject: [PATCH 17/17] chore: added a fix --- .../visitors/orchestrationInternalFunctionCallVisitor.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts b/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts index 9b0d67e8c..d8e614474 100644 --- a/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts +++ b/src/transformers/visitors/orchestrationInternalFunctionCallVisitor.ts @@ -564,6 +564,7 @@ FunctionCall: { decNode.declarations[0].isAccessed = true; decNode.declarations[0].interactsWithSecret = true; state.decNode ??= []; + const decNodeNames = state.decNode.map(node => node.declarations[0].name); decNodeNames.includes(decNode.declarations[0].name) ? state.decNode : state.decNode.push(decNode); } @@ -591,7 +592,10 @@ FunctionCall: { newNode.expression = state.initNode; } - parent._newASTPointer.interactsWithSecret ? state.returnPara.push(returnPara) : ' '; + if(parent._newASTPointer.interactsWithSecret && !(state.returnPara?.includes(returnPara))) { + state.returnPara ??= []; + state.returnPara.push(returnPara); + } }) } else { newNode = buildNode('InternalFunctionCall', {