From 63e1c29bc3f6991ee3053d53531c64306e8a7a6f Mon Sep 17 00:00:00 2001 From: kkahina Date: Fri, 26 Jul 2024 09:38:46 +0100 Subject: [PATCH 01/25] Secret-Array --- test/contracts/Boolean-public.zol | 39 +++++++++++++++++++++++++++++ test/contracts/Non-Secret-Array.zol | 23 +++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 test/contracts/Boolean-public.zol create mode 100644 test/contracts/Non-Secret-Array.zol diff --git a/test/contracts/Boolean-public.zol b/test/contracts/Boolean-public.zol new file mode 100644 index 00000000..7348e9a7 --- /dev/null +++ b/test/contracts/Boolean-public.zol @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: CC0 + +pragma solidity ^0.8.0; + +contract Assign { + + secret bool private a; + secret bool private c; + bool public d; + bool public g; + + + function add( secret uint256 value, secret bool value_bool, bool value_publicbool) public { + secret bool l = true; + bool m = false; + c = a && m && d; + if(value > 10 && !c) { + c=true; + a= value_bool && value_publicbool; + } + if( value < 10) { + a =!c; + c= l || a || m; + } + } + + function addPublic(uint256 value, bool value_publicbool) public { + if (value > 10) { + d = true; + g = value_publicbool; + } + if (value < 10) { + d = false; + g = !value_publicbool; + } + } + + +} diff --git a/test/contracts/Non-Secret-Array.zol b/test/contracts/Non-Secret-Array.zol new file mode 100644 index 00000000..6c14a025 --- /dev/null +++ b/test/contracts/Non-Secret-Array.zol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: CC0 +pragma solidity ^0.8.0; +contract Assign { +secret uint256 private a; +secret uint256 private b; + uint256 public index; +uint256 [] public c; + +function add( uint256 value) public { +c[index] += value; +} + +function add1( uint256 value) public { +c[index] += value; +known a += c[index]; +} + +function add2( uint256 value) public { +c[index] += value; +known a += value; +} + +} \ No newline at end of file From 020da7fa8c5048da3f8c2491a020fd5cad2201c4 Mon Sep 17 00:00:00 2001 From: kkahina Date: Tue, 30 Jul 2024 13:53:39 +0100 Subject: [PATCH 02/25] change smart contract --- src/transformers/visitors/toOrchestrationVisitor.ts | 13 +++++++++++++ test/contracts/Non-Secret-Array.zol | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/transformers/visitors/toOrchestrationVisitor.ts b/src/transformers/visitors/toOrchestrationVisitor.ts index aebf6926..ea88ec51 100644 --- a/src/transformers/visitors/toOrchestrationVisitor.ts +++ b/src/transformers/visitors/toOrchestrationVisitor.ts @@ -88,8 +88,21 @@ const collectIncrements = (stateVarIndicator: StateVariableIndicator | MappingKe const addPublicInput = (path: NodePath, state: any, IDnode: any) => { const { node } = path; let { name } = path.scope.getReferencedIndicator(node, true) || path.node; + + if (!name) { + console.error('Name is not defined for node:', node); + return; +} + + const binding = path.getReferencedBinding(node); if (!['Identifier', 'IndexAccess'].includes(path.nodeType)) return; + + if (!node.baseExpression || !node.baseExpression.interactsWithPublic) { + console.error('Base expression is not defined or does not interact with public:', node); + return; +} + const isCondition = !!path.getAncestorContainedWithin('condition') && path.getAncestorOfType('IfStatement')?.containsSecret; const isForCondition = !!path.getAncestorContainedWithin('condition') && path.getAncestorOfType('ForStatement')?.containsSecret; const isInitializationExpression = !!path.getAncestorContainedWithin('initializationExpression') && path.getAncestorOfType('ForStatement')?.containsSecret; diff --git a/test/contracts/Non-Secret-Array.zol b/test/contracts/Non-Secret-Array.zol index 6c14a025..dd1033f6 100644 --- a/test/contracts/Non-Secret-Array.zol +++ b/test/contracts/Non-Secret-Array.zol @@ -12,7 +12,7 @@ c[index] += value; function add1( uint256 value) public { c[index] += value; -known a += c[index]; + } function add2( uint256 value) public { From d0982185a4d7008d0eb29b13c3093c3685185e7e Mon Sep 17 00:00:00 2001 From: kkahina Date: Mon, 5 Aug 2024 10:00:58 +0100 Subject: [PATCH 03/25] test name --- test/contracts/Non-Secret-Array.zol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/contracts/Non-Secret-Array.zol b/test/contracts/Non-Secret-Array.zol index dd1033f6..6c14a025 100644 --- a/test/contracts/Non-Secret-Array.zol +++ b/test/contracts/Non-Secret-Array.zol @@ -12,7 +12,7 @@ c[index] += value; function add1( uint256 value) public { c[index] += value; - +known a += c[index]; } function add2( uint256 value) public { From ce798cb195c78cf38c1b439d7889db8d4f25d4d8 Mon Sep 17 00:00:00 2001 From: kkahina Date: Mon, 5 Aug 2024 10:40:48 +0100 Subject: [PATCH 04/25] IDnode is correctly assigned and not actually null --- .../visitors/toOrchestrationVisitor.ts | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/transformers/visitors/toOrchestrationVisitor.ts b/src/transformers/visitors/toOrchestrationVisitor.ts index 54639c47..c1b536b9 100644 --- a/src/transformers/visitors/toOrchestrationVisitor.ts +++ b/src/transformers/visitors/toOrchestrationVisitor.ts @@ -116,19 +116,31 @@ const addPublicInput = (path: NodePath, state: any, IDnode: any) => { const { node } = path; let { name } = path.scope.getReferencedIndicator(node, true) || path.node; - if (!name) { - console.error('Name is not defined for node:', node); - return; +// if (!name) { +// console.error('Name is not defined for node:', node); +// return; +// } + +if (IDnode) { + console.log('IDnode before assignment:', IDnode); + IDnode.name = name; // Safe to assign name if IDnode is not null + console.log('IDnode after assignment:', IDnode); +} else { + console.warn('IDnode is null or undefined, unable to set name.'); + // Optionally, handle the case where IDnode is null if needed + return; } +// console.log('Node Path:', path); +// console.log('Referenced Indicator:', path.scope.getReferencedIndicator(node, true)); const binding = path.getReferencedBinding(node); if (!['Identifier', 'IndexAccess'].includes(path.nodeType)) return; - if (!node.baseExpression || !node.baseExpression.interactsWithPublic) { - console.error('Base expression is not defined or does not interact with public:', node); - return; -} +// if (!node.baseExpression || !node.baseExpression.interactsWithPublic) { +// console.error('Base expression is not defined or does not interact with public:', node); +// return; +// } const isCondition = !!path.getAncestorContainedWithin('condition') && path.getAncestorOfType('IfStatement')?.containsSecret; const isForCondition = !!path.getAncestorContainedWithin('condition') && path.getAncestorOfType('ForStatement')?.containsSecret; From 96007eeda80bbe14943aaade8c9d9256b482b729 Mon Sep 17 00:00:00 2001 From: kkahina Date: Mon, 5 Aug 2024 13:22:29 +0100 Subject: [PATCH 05/25] fixe zapp extra code --- test/contracts/Non-Secret-Array.zol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/contracts/Non-Secret-Array.zol b/test/contracts/Non-Secret-Array.zol index 6c14a025..e21aa65a 100644 --- a/test/contracts/Non-Secret-Array.zol +++ b/test/contracts/Non-Secret-Array.zol @@ -10,8 +10,8 @@ function add( uint256 value) public { c[index] += value; } -function add1( uint256 value) public { -c[index] += value; +function add1() public { + known a += c[index]; } From b8160cb8b88576e60d55c717b86edf85aca8da7f Mon Sep 17 00:00:00 2001 From: kkahina Date: Wed, 7 Aug 2024 14:59:20 +0100 Subject: [PATCH 06/25] Index duplicate fixed --- test/contracts/Non-Secret-Array.zol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/contracts/Non-Secret-Array.zol b/test/contracts/Non-Secret-Array.zol index e21aa65a..6c14a025 100644 --- a/test/contracts/Non-Secret-Array.zol +++ b/test/contracts/Non-Secret-Array.zol @@ -10,8 +10,8 @@ function add( uint256 value) public { c[index] += value; } -function add1() public { - +function add1( uint256 value) public { +c[index] += value; known a += c[index]; } From 6547e7fb7064a240a15a5d492a46c796550514e8 Mon Sep 17 00:00:00 2001 From: kkahina Date: Fri, 9 Aug 2024 09:10:29 +0100 Subject: [PATCH 07/25] Idnode insertion corrected --- .../visitors/toOrchestrationVisitor.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/transformers/visitors/toOrchestrationVisitor.ts b/src/transformers/visitors/toOrchestrationVisitor.ts index 6124d147..6947a21a 100644 --- a/src/transformers/visitors/toOrchestrationVisitor.ts +++ b/src/transformers/visitors/toOrchestrationVisitor.ts @@ -122,15 +122,15 @@ const addPublicInput = (path: NodePath, state: any, IDnode: any) => { // return; // } -if (IDnode) { - console.log('IDnode before assignment:', IDnode); - IDnode.name = name; // Safe to assign name if IDnode is not null - console.log('IDnode after assignment:', IDnode); -} else { - console.warn('IDnode is null or undefined, unable to set name.'); - // Optionally, handle the case where IDnode is null if needed - return; -} +// if (IDnode) { +// console.log('IDnode before assignment:', IDnode); +// IDnode.name = name; // Safe to assign name if IDnode is not null +// console.log('IDnode after assignment:', IDnode); +// } else { +// console.warn('IDnode is null or undefined, unable to set name.'); +// // Optionally, handle the case where IDnode is null if needed +// return; +// } // console.log('Node Path:', path); // console.log('Referenced Indicator:', path.scope.getReferencedIndicator(node, true)); From f776901b93083a2da546688819029b2c6f24217a Mon Sep 17 00:00:00 2001 From: kkahina Date: Mon, 12 Aug 2024 16:06:57 +0100 Subject: [PATCH 08/25] init the Array lenght --- .../javascript/raw/toOrchestration.ts | 1 + .../visitors/toOrchestrationVisitor.ts | 44 ++++++++++++++----- test/contracts/Non-Secret-Array.zol | 6 +-- 3 files changed, 37 insertions(+), 14 deletions(-) diff --git a/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts b/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts index a8d141a8..1f4c1903 100644 --- a/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts +++ b/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts @@ -1011,6 +1011,7 @@ export const OrchestrationCodeBoilerPlate: any = (node: any) => { } }); } + return { statements: [ `\n\n// Send transaction to the blockchain: diff --git a/src/transformers/visitors/toOrchestrationVisitor.ts b/src/transformers/visitors/toOrchestrationVisitor.ts index 6947a21a..f26ab84f 100644 --- a/src/transformers/visitors/toOrchestrationVisitor.ts +++ b/src/transformers/visitors/toOrchestrationVisitor.ts @@ -121,16 +121,37 @@ const addPublicInput = (path: NodePath, state: any, IDnode: any) => { // console.error('Name is not defined for node:', node); // return; // } +let num_modifiers=0; // if (IDnode) { // console.log('IDnode before assignment:', IDnode); -// IDnode.name = name; // Safe to assign name if IDnode is not null + +// // Apply logic to adjust the name if needed +// if (num_modifiers !== 0) { +// if (IDnode.name === node.name) { +// IDnode.name += `_${num_modifiers}`; +// } else { +// IDnode.name = `${node.name}_${num_modifiers}`; +// } +// } else { +// IDnode.name = name; // Just set the name if no modifiers +// } // console.log('IDnode after assignment:', IDnode); // } else { // console.warn('IDnode is null or undefined, unable to set name.'); -// // Optionally, handle the case where IDnode is null if needed +// // Optionally handle the null case, or just return as needed // return; // } + +if (IDnode) { + console.log('IDnode before assignment:', IDnode); + IDnode.name = name; // Safe to assign name if IDnode is not null + console.log('IDnode after assignment:', IDnode); +} else { + console.warn('IDnode is null or undefined, unable to set name.'); + // Optionally, handle the case where IDnode is null if needed + return; +} // console.log('Node Path:', path); // console.log('Referenced Indicator:', path.scope.getReferencedIndicator(node, true)); @@ -210,7 +231,7 @@ const addPublicInput = (path: NodePath, state: any, IDnode: any) => { const statements = fnDefNode.node._newASTPointer.body.statements; - let num_modifiers=0; + // let num_modifiers=0; // For each statement that modifies the public variable previously, we need to ensure that the modified variable is stored for later. // We also need that the original public variable is updated, e.g if the statement is index_2 = index +1, we need an extra statement index = index_2. modifiedBeforePaths?.forEach((p: NodePath) => { @@ -328,14 +349,15 @@ const addPublicInput = (path: NodePath, state: any, IDnode: any) => { } } }); - // We ensure here that the public variable used has the correct name, e.g index_2 instead of index. - if (num_modifiers != 0) { - if (IDnode.name === node.name){ - IDnode.name += `_${num_modifiers}`; - } else { - IDnode.name = `${node.name}_${num_modifiers}`; - } - } + + //We ensure here that the public variable used has the correct name, e.g index_2 instead of index. + // if (num_modifiers != 0) { + // if (IDnode.name === node.name){ + // IDnode.name += `_${num_modifiers}`; + // } else { + // IDnode.name = `${node.name}_${num_modifiers}`; + // } + // } // After the non-secret variables have been modified we need to reset the original variable name to its initial value. // e.g. index = index_init. if (node.nodeType !== 'IndexAccess') { diff --git a/test/contracts/Non-Secret-Array.zol b/test/contracts/Non-Secret-Array.zol index 6c14a025..c3b82919 100644 --- a/test/contracts/Non-Secret-Array.zol +++ b/test/contracts/Non-Secret-Array.zol @@ -4,15 +4,15 @@ contract Assign { secret uint256 private a; secret uint256 private b; uint256 public index; -uint256 [] public c; +uint256 [3] public c; -function add( uint256 value) public { +function add( uint256 value) public { c[index] += value; } function add1( uint256 value) public { c[index] += value; -known a += c[index]; + } function add2( uint256 value) public { From 81532367b53e5518739584644acf09d6ddd5de3b Mon Sep 17 00:00:00 2001 From: kkahina Date: Tue, 13 Aug 2024 10:54:00 +0100 Subject: [PATCH 09/25] index init --- privatekey | 8 ++++++++ privatekey.pub | 1 + src/transformers/visitors/toOrchestrationVisitor.ts | 6 ++++++ test/contracts/Non-Secret-Array.zol | 4 +++- 4 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 privatekey create mode 100644 privatekey.pub diff --git a/privatekey b/privatekey new file mode 100644 index 00000000..7197a0b7 --- /dev/null +++ b/privatekey @@ -0,0 +1,8 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABASCLRvwc +n77yJFa5VzDXRKAAAAGAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIERVnHdjXuVDYprn +Qgq++Lv012NyXBzX+1Ea/6RUgvRGAAAAoB52MIATVWDsWlmsmifcL9SlGPmFw+Sh0qHacl +W/1BWDhEb2Wsz0TIiLx3ujAjAwKpRatROFkBM/BcA346oBGT01EtCMl+KNYSB2pYIp4Q4k +XAwR3lLVIjH1PNFOIyPL/FTHluYSSPpVdBINE9qa8Lq0cp4Rshru7MV9X74AP1Qddl9zNp +zxo/sLgwe7IkdxxGbJJgIzk4fAJC+rDUcjvtQ= +-----END OPENSSH PRIVATE KEY----- diff --git a/privatekey.pub b/privatekey.pub new file mode 100644 index 00000000..a1972aac --- /dev/null +++ b/privatekey.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIERVnHdjXuVDYprnQgq++Lv012NyXBzX+1Ea/6RUgvRG kahina.khacef@uk.ey.com diff --git a/src/transformers/visitors/toOrchestrationVisitor.ts b/src/transformers/visitors/toOrchestrationVisitor.ts index f26ab84f..ed3a4fb4 100644 --- a/src/transformers/visitors/toOrchestrationVisitor.ts +++ b/src/transformers/visitors/toOrchestrationVisitor.ts @@ -152,6 +152,12 @@ if (IDnode) { // Optionally, handle the case where IDnode is null if needed return; } + +if (!node.baseExpression || !node.baseExpression.interactsWithPublic){ + console.error('2222222222222222222 base expression is not defined or does not interact with public:',node); + return; + +} // console.log('Node Path:', path); // console.log('Referenced Indicator:', path.scope.getReferencedIndicator(node, true)); diff --git a/test/contracts/Non-Secret-Array.zol b/test/contracts/Non-Secret-Array.zol index c3b82919..c8800d14 100644 --- a/test/contracts/Non-Secret-Array.zol +++ b/test/contracts/Non-Secret-Array.zol @@ -3,7 +3,8 @@ pragma solidity ^0.8.0; contract Assign { secret uint256 private a; secret uint256 private b; - uint256 public index; +uint256 public index; +uint256 public d; uint256 [3] public c; function add( uint256 value) public { @@ -12,6 +13,7 @@ c[index] += value; function add1( uint256 value) public { c[index] += value; +known a +=d; } From 1870b71ca7aa613db39a4db81232a30b83a0717c Mon Sep 17 00:00:00 2001 From: kkahina Date: Tue, 13 Aug 2024 11:29:34 +0100 Subject: [PATCH 10/25] fix for a+=value --- test/contracts/Non-Secret-Array.zol | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/contracts/Non-Secret-Array.zol b/test/contracts/Non-Secret-Array.zol index c8800d14..7334981b 100644 --- a/test/contracts/Non-Secret-Array.zol +++ b/test/contracts/Non-Secret-Array.zol @@ -4,20 +4,22 @@ contract Assign { secret uint256 private a; secret uint256 private b; uint256 public index; -uint256 public d; uint256 [3] public c; function add( uint256 value) public { +require(index < c.length, "Index out of bounds"); c[index] += value; } function add1( uint256 value) public { +require(index < c.length, "Index out of bounds"); c[index] += value; -known a +=d; +known a +=value; } function add2( uint256 value) public { + require(index < c.length, "Index out of bounds"); c[index] += value; known a += value; } From 11770a38ff27ead24733965a1d7fdf164f33ef47 Mon Sep 17 00:00:00 2001 From: kkahina Date: Tue, 13 Aug 2024 16:17:57 +0100 Subject: [PATCH 11/25] fixe arrayLength ContractVisitor --- .../visitors/toContractVisitor.ts | 13 +++++- .../visitors/toOrchestrationVisitor.ts | 44 +++++++++---------- test/contracts/Non-Secret-Array.zol | 13 +++--- 3 files changed, 40 insertions(+), 30 deletions(-) diff --git a/src/transformers/visitors/toContractVisitor.ts b/src/transformers/visitors/toContractVisitor.ts index 06f10742..f92b47da 100644 --- a/src/transformers/visitors/toContractVisitor.ts +++ b/src/transformers/visitors/toContractVisitor.ts @@ -59,8 +59,19 @@ const findCustomInputsVisitor = (thisPath: NodePath, thisState: any) => { ) { thisState.customInputs ??= []; const type = binding.node.typeName.nodeType === 'Mapping' ? binding.node.typeName.valueType.name : binding.node.typeName.name; + const isConstantArray = thisPath.isConstantArray(); + const arrayLength = isConstantArray && thisPath.node.typeName?.length ? thisPath.node.typeName.length.value : false; + console.log('isConstantArray:', isConstantArray); + console.log('arrayLength:', arrayLength); if (!thisState.customInputs.some((input: any) => input.name === indicator?.name)) - thisState.customInputs.push({name: indicator?.name, typeName: {name: type}, isConstantArray: thisPath.isConstantArray() ? thisPath.node.typeName.length.value : false, inCircuit: true, isReturn: false }); + thisState.customInputs.push({ + name: indicator?.name, + typeName: { name: type }, + isConstantArray: arrayLength, + inCircuit: true, + isReturn: false + }); + } }; diff --git a/src/transformers/visitors/toOrchestrationVisitor.ts b/src/transformers/visitors/toOrchestrationVisitor.ts index ed3a4fb4..846d44c4 100644 --- a/src/transformers/visitors/toOrchestrationVisitor.ts +++ b/src/transformers/visitors/toOrchestrationVisitor.ts @@ -123,36 +123,36 @@ const addPublicInput = (path: NodePath, state: any, IDnode: any) => { // } let num_modifiers=0; -// if (IDnode) { -// console.log('IDnode before assignment:', IDnode); - -// // Apply logic to adjust the name if needed -// if (num_modifiers !== 0) { -// if (IDnode.name === node.name) { -// IDnode.name += `_${num_modifiers}`; -// } else { -// IDnode.name = `${node.name}_${num_modifiers}`; -// } -// } else { -// IDnode.name = name; // Just set the name if no modifiers -// } -// console.log('IDnode after assignment:', IDnode); -// } else { -// console.warn('IDnode is null or undefined, unable to set name.'); -// // Optionally handle the null case, or just return as needed -// return; -// } - if (IDnode) { console.log('IDnode before assignment:', IDnode); - IDnode.name = name; // Safe to assign name if IDnode is not null + + // Apply logic to adjust the name if needed + if (num_modifiers !== 0) { + if (IDnode.name === node.name) { + IDnode.name += `_${num_modifiers}`; + } else { + IDnode.name = `${node.name}_${num_modifiers}`; + } + } else { + IDnode.name = name; // Just set the name if no modifiers + } console.log('IDnode after assignment:', IDnode); } else { console.warn('IDnode is null or undefined, unable to set name.'); - // Optionally, handle the case where IDnode is null if needed + // Optionally handle the null case, or just return as needed return; } +// if (IDnode) { +// console.log('IDnode before assignment:', IDnode); +// IDnode.name = name; // Safe to assign name if IDnode is not null +// console.log('IDnode after assignment:', IDnode); +// } else { +// console.warn('IDnode is null or undefined, unable to set name.'); +// // Optionally, handle the case where IDnode is null if needed +// return; +// } + if (!node.baseExpression || !node.baseExpression.interactsWithPublic){ console.error('2222222222222222222 base expression is not defined or does not interact with public:',node); return; diff --git a/test/contracts/Non-Secret-Array.zol b/test/contracts/Non-Secret-Array.zol index 7334981b..23f7c97e 100644 --- a/test/contracts/Non-Secret-Array.zol +++ b/test/contracts/Non-Secret-Array.zol @@ -1,27 +1,26 @@ // SPDX-License-Identifier: CC0 + pragma solidity ^0.8.0; contract Assign { secret uint256 private a; secret uint256 private b; uint256 public index; -uint256 [3] public c; +uint256[3] public c; function add( uint256 value) public { -require(index < c.length, "Index out of bounds"); -c[index] += value; + +c[0] += value; } function add1( uint256 value) public { require(index < c.length, "Index out of bounds"); c[index] += value; -known a +=value; - +known a += c[index]; } function add2( uint256 value) public { - require(index < c.length, "Index out of bounds"); + c[index] += value; known a += value; } - } \ No newline at end of file From b3b4b717a8163f7b6f8a7063872ef90b62ba3739 Mon Sep 17 00:00:00 2001 From: kkahina Date: Mon, 19 Aug 2024 06:29:59 +0100 Subject: [PATCH 12/25] init lenght array --- src/transformers/visitors/toCircuitVisitor.ts | 127 ++++++++++-------- .../visitors/toContractVisitor.ts | 3 +- .../visitors/toOrchestrationVisitor.ts | 28 ---- test/contracts/Non-Secret-Array.zol | 4 +- 4 files changed, 77 insertions(+), 85 deletions(-) diff --git a/src/transformers/visitors/toCircuitVisitor.ts b/src/transformers/visitors/toCircuitVisitor.ts index db99291a..ce83201c 100644 --- a/src/transformers/visitors/toCircuitVisitor.ts +++ b/src/transformers/visitors/toCircuitVisitor.ts @@ -84,66 +84,72 @@ const findStatementId = (statements: any, ID: number) => { // public variables that interact with the secret also need to be modified within the circuit. const publicVariables = (path: NodePath, state: any, IDnode: any) => { - const {parent, node } = path; - // Break if the identifier is a mapping or array. - if ( parent.indexExpression && parent.baseExpression === node ) { - return;} + const { parent, node } = path; + + // Ignore if it's an index access + if (parent.indexExpression && parent.baseExpression === node) { + return; + } + const binding = path.getReferencedBinding(node); if (!['Identifier', 'IndexAccess'].includes(path.nodeType)) return; - - // If there is a statment where a secret variable interacts with a public one, we need to adjust previous statements where the public variable was modified. - + // Check if the variable is a public variable interacting with secrets directly or indirectly if ( binding instanceof VariableBinding && - (node.interactsWithSecret || node.baseExpression?.interactsWithSecret) && + (node.interactsWithSecret || node.baseExpression?.interactsWithSecret || node.interactsWithPublic) && (node.interactsWithPublic || node.baseExpression?.interactsWithPublic) && - binding.stateVariable && !binding.isSecret - ) - { + binding.stateVariable && !binding.isSecret + ) { const fnDefNode = path.getAncestorOfType('FunctionDefinition'); if (!fnDefNode) throw new Error(`Not in a function`); const modifiedBeforePaths = path.scope.getReferencedIndicator(node, true)?.modifyingPaths?.filter((p: NodePath) => p.node.id < node.id); const statements = fnDefNode.node._newASTPointer.body.statements; - let num_modifiers=0; - // For each statement that modifies the public variable previously, we need to ensure that the modified variable is stored for later. - // We also need that the original public variable is updated, e.g if the statement is index_2 = index +1, we need an extra statement index = index_2. + let num_modifiers = 0; + + // Handle previous modifications to public variables modifiedBeforePaths?.forEach((p: NodePath) => { const expressionId = p.getAncestorOfType('ExpressionStatement')?.node?.id; if (expressionId) { if (path.containerName !== 'indexExpression') { num_modifiers++; - } - let {expNode, location} = findStatementId(statements, expressionId); + } + let { expNode, location } = findStatementId(statements, expressionId); if (expNode && !expNode.isAccessed) { expNode.isAccessed = true; - if((expNode.expression && expNode.expression.leftHandSide && expNode.expression.leftHandSide?.name === node.name) || - (expNode.initialValue && expNode.initialValue.leftHandSide && expNode.initialValue.leftHandSide?.name === node.name) || - (expNode.expression.initialValue && expNode.expression.initialValue.name === node.name)){ - if (num_modifiers !=0){ + if ( + (expNode.expression && expNode.expression.leftHandSide?.name === node.name) || + (expNode.initialValue && expNode.initialValue.leftHandSide?.name === node.name) || + (expNode.expression.initialValue && expNode.expression.initialValue.name === node.name) + ) { + if (num_modifiers != 0) { const initInnerNode = buildNode('Assignment', { - leftHandSide: buildNode('Identifier', { name: `${node.name}_${num_modifiers}`, subType: 'generalNumber' }), + leftHandSide: buildNode('Identifier', { name: `${node.name}_${num_modifiers}`, subType: 'generalNumber' }), operator: '=', rightHandSide: buildNode('Identifier', { name: `${node.name}`, subType: 'generalNumber' }) }); const newNode1 = buildNode('ExpressionStatement', { - expression: initInnerNode, - interactsWithSecret: true, - isVarDec: true, + expression: initInnerNode, + interactsWithSecret: true, + isVarDec: true, }); newNode1.outsideIf = true; - if (location.index!== -1) { - if (location.trueIndex !== -1){ fnDefNode.node._newASTPointer.body.statements[location.index].trueBody.splice(location.trueIndex + 1, 0, newNode1); } - else if (location.falseIndex !== -1){ fnDefNode.node._newASTPointer.body.statements[location.index].falseBody.splice(location.falseIndex + 1, 0, newNode1); } - else {fnDefNode.node._newASTPointer.body.statements.splice(location.index + 1, 0, newNode1);} + if (location.index !== -1) { + if (location.trueIndex !== -1) { + fnDefNode.node._newASTPointer.body.statements[location.index].trueBody.splice(location.trueIndex + 1, 0, newNode1); + } else if (location.falseIndex !== -1) { + fnDefNode.node._newASTPointer.body.statements[location.index].falseBody.splice(location.falseIndex + 1, 0, newNode1); + } else { + fnDefNode.node._newASTPointer.body.statements.splice(location.index + 1, 0, newNode1); + } } } - } else{ + } else { let modName = expNode.expression.initialValue?.leftHandSide?.name || expNode.expression.initialValue?.name || expNode.expression.leftHandSide?.name; const InnerNode = buildNode('Assignment', { - leftHandSide: buildNode('Identifier', { name: `${node.name}`, subType: 'generalNumber' }), + leftHandSide: buildNode('Identifier', { name: `${node.name}`, subType: 'generalNumber' }), operator: '=', rightHandSide: buildNode('Identifier', { name: `${modName}`, subType: 'generalNumber' }) }); @@ -152,34 +158,43 @@ const publicVariables = (path: NodePath, state: any, IDnode: any) => { interactsWithSecret: true, }); newNode1.outsideIf = true; - if (location.index!== -1) { - if (location.trueIndex !== -1){ fnDefNode.node._newASTPointer.body.statements[location.index].trueBody.splice(location.trueIndex + 1, 0, newNode1); } - else if (location.falseIndex !== -1){ fnDefNode.node._newASTPointer.body.statements[location.index].falseBody.splice(location.falseIndex + 1, 0, newNode1); } - else {fnDefNode.node._newASTPointer.body.statements.splice(location.index + 1, 0, newNode1);} + if (location.index !== -1) { + if (location.trueIndex !== -1) { + fnDefNode.node._newASTPointer.body.statements[location.index].trueBody.splice(location.trueIndex + 1, 0, newNode1); + } else if (location.falseIndex !== -1) { + fnDefNode.node._newASTPointer.body.statements[location.index].falseBody.splice(location.falseIndex + 1, 0, newNode1); + } else { + fnDefNode.node._newASTPointer.body.statements.splice(location.index + 1, 0, newNode1); + } } - if (`${modName}` !== `${node.name}_${num_modifiers}` && num_modifiers !==0){ + if (`${modName}` !== `${node.name}_${num_modifiers}` && num_modifiers !== 0) { const initInnerNode1 = buildNode('Assignment', { - leftHandSide: buildNode('Identifier', { name: `${node.name}_${num_modifiers}`, subType: 'generalNumber' }), + leftHandSide: buildNode('Identifier', { name: `${node.name}_${num_modifiers}`, subType: 'generalNumber' }), operator: '=', rightHandSide: buildNode('Identifier', { name: `${node.name}`, subType: 'generalNumber' }) }); const newNode2 = buildNode('ExpressionStatement', { - expression: initInnerNode1, - interactsWithSecret: true, - isVarDec: true, + expression: initInnerNode1, + interactsWithSecret: true, + isVarDec: true, }); newNode2.outsideIf = true; - if (location.index!== -1) { - if (location.trueIndex !== -1){ fnDefNode.node._newASTPointer.body.statements[location.index].trueBody.splice(location.trueIndex + 2, 0, newNode2); } - else if (location.falseIndex !== -1){ fnDefNode.node._newASTPointer.body.statements[location.index].falseBody.splice(location.falseIndex + 2, 0, newNode2); } - else {fnDefNode.node._newASTPointer.body.statements.splice(location.index + 2, 0, newNode2);} + if (location.index !== -1) { + if (location.trueIndex !== -1) { + fnDefNode.node._newASTPointer.body.statements[location.index].trueBody.splice(location.trueIndex + 2, 0, newNode2); + } else if (location.falseIndex !== -1) { + fnDefNode.node._newASTPointer.body.statements[location.index].falseBody.splice(location.falseIndex + 2, 0, newNode2); + } else { + fnDefNode.node._newASTPointer.body.statements.splice(location.index + 2, 0, newNode2); + } } } } } } }); - // We ensure here that the public variable used has the correct name, e.g index_2 instead of index. + + // Ensure correct name for the public variable if (num_modifiers != 0) { if (IDnode.name === node.name){ IDnode.name += `_${num_modifiers}`; @@ -187,8 +202,8 @@ const publicVariables = (path: NodePath, state: any, IDnode: any) => { IDnode.name = `${node.name}_${num_modifiers}`; } } - // After the non-secret variables have been modified we need to reset the original variable name to its initial value. - // e.g. index = index_init. + + // Reset the original variable name to its initial value for (let i = fnDefNode.node._newASTPointer.body.statements.length - 1; i >= 0; i--) { const p = fnDefNode.node._newASTPointer.body.statements[i]; if (p.expression?.rightHandSide?.name === `${node.name}_init`) { @@ -196,33 +211,39 @@ const publicVariables = (path: NodePath, state: any, IDnode: any) => { } } const endNodeInit = buildNode('Assignment', { - leftHandSide: buildNode('Identifier', { name: `${node.name}`, subType: 'generalNumber' }), + leftHandSide: buildNode('Identifier', { name: `${node.name}`, subType: 'generalNumber' }), operator: '=', rightHandSide: buildNode('Identifier', { name: `${node.name}_init`, subType: 'generalNumber' }), }); const endNode = buildNode('ExpressionStatement', { - expression: endNodeInit, - interactsWithSecret: true, - isVarDec: false, + expression: endNodeInit, + interactsWithSecret: true, + isVarDec: false, }); endNode.isEndInit = true; fnDefNode.node._newASTPointer.body.statements.push(endNode); } - // We no longer need this because index expression nodes are not input. - //if (['Identifier', 'IndexAccess'].includes(node.indexExpression?.nodeType)) publicVariables(NodePath.getPath(node.indexExpression), state, null); } + //Visitor for publicVariables const publicVariablesVisitor = (thisPath: NodePath, thisState: any) => { const { node } = thisPath; let { name } = node; if (!['Identifier', 'IndexAccess'].includes(thisPath.nodeType)) return; + + const binding = thisPath.getReferencedBinding(node); - if ( (binding instanceof VariableBinding) && !binding.isSecret && + + + if ( binding instanceof VariableBinding && + (node.interactsWithPublic || node.baseExpression?.interactsWithPublic) && + !binding.isSecret && binding.stateVariable && thisPath.getAncestorContainedWithin('rightHandSide') ){ } else{ name = thisPath.scope.getIdentifierMappingKeyName(node); } + const newNode = buildNode( node.nodeType, { name, type: node.typeDescriptions?.typeString }, diff --git a/src/transformers/visitors/toContractVisitor.ts b/src/transformers/visitors/toContractVisitor.ts index f92b47da..6e740950 100644 --- a/src/transformers/visitors/toContractVisitor.ts +++ b/src/transformers/visitors/toContractVisitor.ts @@ -61,8 +61,7 @@ const findCustomInputsVisitor = (thisPath: NodePath, thisState: any) => { const type = binding.node.typeName.nodeType === 'Mapping' ? binding.node.typeName.valueType.name : binding.node.typeName.name; const isConstantArray = thisPath.isConstantArray(); const arrayLength = isConstantArray && thisPath.node.typeName?.length ? thisPath.node.typeName.length.value : false; - console.log('isConstantArray:', isConstantArray); - console.log('arrayLength:', arrayLength); + if (!thisState.customInputs.some((input: any) => input.name === indicator?.name)) thisState.customInputs.push({ name: indicator?.name, diff --git a/src/transformers/visitors/toOrchestrationVisitor.ts b/src/transformers/visitors/toOrchestrationVisitor.ts index 846d44c4..02de3e0e 100644 --- a/src/transformers/visitors/toOrchestrationVisitor.ts +++ b/src/transformers/visitors/toOrchestrationVisitor.ts @@ -117,16 +117,9 @@ const addPublicInput = (path: NodePath, state: any, IDnode: any) => { const { node } = path; let { name } = path.scope.getReferencedIndicator(node, true) || path.node; -// if (!name) { -// console.error('Name is not defined for node:', node); -// return; -// } let num_modifiers=0; if (IDnode) { - console.log('IDnode before assignment:', IDnode); - - // Apply logic to adjust the name if needed if (num_modifiers !== 0) { if (IDnode.name === node.name) { IDnode.name += `_${num_modifiers}`; @@ -136,39 +129,18 @@ if (IDnode) { } else { IDnode.name = name; // Just set the name if no modifiers } - console.log('IDnode after assignment:', IDnode); } else { - console.warn('IDnode is null or undefined, unable to set name.'); - // Optionally handle the null case, or just return as needed return; } -// if (IDnode) { -// console.log('IDnode before assignment:', IDnode); -// IDnode.name = name; // Safe to assign name if IDnode is not null -// console.log('IDnode after assignment:', IDnode); -// } else { -// console.warn('IDnode is null or undefined, unable to set name.'); -// // Optionally, handle the case where IDnode is null if needed -// return; -// } - if (!node.baseExpression || !node.baseExpression.interactsWithPublic){ - console.error('2222222222222222222 base expression is not defined or does not interact with public:',node); return; } -// console.log('Node Path:', path); -// console.log('Referenced Indicator:', path.scope.getReferencedIndicator(node, true)); - const binding = path.getReferencedBinding(node); if (!['Identifier', 'IndexAccess'].includes(path.nodeType)) return; -// if (!node.baseExpression || !node.baseExpression.interactsWithPublic) { -// console.error('Base expression is not defined or does not interact with public:', node); -// return; -// } const isCondition = !!path.getAncestorContainedWithin('condition') && path.getAncestorOfType('IfStatement')?.containsSecret; const isForCondition = !!path.getAncestorContainedWithin('condition') && path.getAncestorOfType('ForStatement')?.containsSecret; diff --git a/test/contracts/Non-Secret-Array.zol b/test/contracts/Non-Secret-Array.zol index 23f7c97e..b7bf68f9 100644 --- a/test/contracts/Non-Secret-Array.zol +++ b/test/contracts/Non-Secret-Array.zol @@ -14,8 +14,8 @@ c[0] += value; function add1( uint256 value) public { require(index < c.length, "Index out of bounds"); -c[index] += value; -known a += c[index]; +c[0] += value; +known a += value; } function add2( uint256 value) public { From fcddacbb851735c3b81420f26307cdea50d0e8dc Mon Sep 17 00:00:00 2001 From: kkahina Date: Mon, 19 Aug 2024 08:16:02 +0100 Subject: [PATCH 13/25] fixe public variable --- src/transformers/visitors/toCircuitVisitor.ts | 127 ++++++++---------- 1 file changed, 53 insertions(+), 74 deletions(-) diff --git a/src/transformers/visitors/toCircuitVisitor.ts b/src/transformers/visitors/toCircuitVisitor.ts index ce83201c..db99291a 100644 --- a/src/transformers/visitors/toCircuitVisitor.ts +++ b/src/transformers/visitors/toCircuitVisitor.ts @@ -84,72 +84,66 @@ const findStatementId = (statements: any, ID: number) => { // public variables that interact with the secret also need to be modified within the circuit. const publicVariables = (path: NodePath, state: any, IDnode: any) => { - const { parent, node } = path; - - // Ignore if it's an index access - if (parent.indexExpression && parent.baseExpression === node) { - return; - } - + const {parent, node } = path; + // Break if the identifier is a mapping or array. + if ( parent.indexExpression && parent.baseExpression === node ) { + return;} const binding = path.getReferencedBinding(node); if (!['Identifier', 'IndexAccess'].includes(path.nodeType)) return; + + // If there is a statment where a secret variable interacts with a public one, we need to adjust previous statements where the public variable was modified. - // Check if the variable is a public variable interacting with secrets directly or indirectly + if ( binding instanceof VariableBinding && - (node.interactsWithSecret || node.baseExpression?.interactsWithSecret || node.interactsWithPublic) && + (node.interactsWithSecret || node.baseExpression?.interactsWithSecret) && (node.interactsWithPublic || node.baseExpression?.interactsWithPublic) && - binding.stateVariable && !binding.isSecret - ) { + binding.stateVariable && !binding.isSecret + ) + { const fnDefNode = path.getAncestorOfType('FunctionDefinition'); if (!fnDefNode) throw new Error(`Not in a function`); const modifiedBeforePaths = path.scope.getReferencedIndicator(node, true)?.modifyingPaths?.filter((p: NodePath) => p.node.id < node.id); const statements = fnDefNode.node._newASTPointer.body.statements; - let num_modifiers = 0; - - // Handle previous modifications to public variables + let num_modifiers=0; + // For each statement that modifies the public variable previously, we need to ensure that the modified variable is stored for later. + // We also need that the original public variable is updated, e.g if the statement is index_2 = index +1, we need an extra statement index = index_2. modifiedBeforePaths?.forEach((p: NodePath) => { const expressionId = p.getAncestorOfType('ExpressionStatement')?.node?.id; if (expressionId) { if (path.containerName !== 'indexExpression') { num_modifiers++; - } - let { expNode, location } = findStatementId(statements, expressionId); + } + let {expNode, location} = findStatementId(statements, expressionId); if (expNode && !expNode.isAccessed) { expNode.isAccessed = true; - if ( - (expNode.expression && expNode.expression.leftHandSide?.name === node.name) || - (expNode.initialValue && expNode.initialValue.leftHandSide?.name === node.name) || - (expNode.expression.initialValue && expNode.expression.initialValue.name === node.name) - ) { - if (num_modifiers != 0) { + if((expNode.expression && expNode.expression.leftHandSide && expNode.expression.leftHandSide?.name === node.name) || + (expNode.initialValue && expNode.initialValue.leftHandSide && expNode.initialValue.leftHandSide?.name === node.name) || + (expNode.expression.initialValue && expNode.expression.initialValue.name === node.name)){ + if (num_modifiers !=0){ const initInnerNode = buildNode('Assignment', { - leftHandSide: buildNode('Identifier', { name: `${node.name}_${num_modifiers}`, subType: 'generalNumber' }), + leftHandSide: buildNode('Identifier', { name: `${node.name}_${num_modifiers}`, subType: 'generalNumber' }), operator: '=', rightHandSide: buildNode('Identifier', { name: `${node.name}`, subType: 'generalNumber' }) }); const newNode1 = buildNode('ExpressionStatement', { - expression: initInnerNode, - interactsWithSecret: true, - isVarDec: true, + expression: initInnerNode, + interactsWithSecret: true, + isVarDec: true, }); newNode1.outsideIf = true; - if (location.index !== -1) { - if (location.trueIndex !== -1) { - fnDefNode.node._newASTPointer.body.statements[location.index].trueBody.splice(location.trueIndex + 1, 0, newNode1); - } else if (location.falseIndex !== -1) { - fnDefNode.node._newASTPointer.body.statements[location.index].falseBody.splice(location.falseIndex + 1, 0, newNode1); - } else { - fnDefNode.node._newASTPointer.body.statements.splice(location.index + 1, 0, newNode1); - } + if (location.index!== -1) { + if (location.trueIndex !== -1){ fnDefNode.node._newASTPointer.body.statements[location.index].trueBody.splice(location.trueIndex + 1, 0, newNode1); } + else if (location.falseIndex !== -1){ fnDefNode.node._newASTPointer.body.statements[location.index].falseBody.splice(location.falseIndex + 1, 0, newNode1); } + else {fnDefNode.node._newASTPointer.body.statements.splice(location.index + 1, 0, newNode1);} } } - } else { + } else{ let modName = expNode.expression.initialValue?.leftHandSide?.name || expNode.expression.initialValue?.name || expNode.expression.leftHandSide?.name; const InnerNode = buildNode('Assignment', { - leftHandSide: buildNode('Identifier', { name: `${node.name}`, subType: 'generalNumber' }), + leftHandSide: buildNode('Identifier', { name: `${node.name}`, subType: 'generalNumber' }), operator: '=', rightHandSide: buildNode('Identifier', { name: `${modName}`, subType: 'generalNumber' }) }); @@ -158,43 +152,34 @@ const publicVariables = (path: NodePath, state: any, IDnode: any) => { interactsWithSecret: true, }); newNode1.outsideIf = true; - if (location.index !== -1) { - if (location.trueIndex !== -1) { - fnDefNode.node._newASTPointer.body.statements[location.index].trueBody.splice(location.trueIndex + 1, 0, newNode1); - } else if (location.falseIndex !== -1) { - fnDefNode.node._newASTPointer.body.statements[location.index].falseBody.splice(location.falseIndex + 1, 0, newNode1); - } else { - fnDefNode.node._newASTPointer.body.statements.splice(location.index + 1, 0, newNode1); - } + if (location.index!== -1) { + if (location.trueIndex !== -1){ fnDefNode.node._newASTPointer.body.statements[location.index].trueBody.splice(location.trueIndex + 1, 0, newNode1); } + else if (location.falseIndex !== -1){ fnDefNode.node._newASTPointer.body.statements[location.index].falseBody.splice(location.falseIndex + 1, 0, newNode1); } + else {fnDefNode.node._newASTPointer.body.statements.splice(location.index + 1, 0, newNode1);} } - if (`${modName}` !== `${node.name}_${num_modifiers}` && num_modifiers !== 0) { + if (`${modName}` !== `${node.name}_${num_modifiers}` && num_modifiers !==0){ const initInnerNode1 = buildNode('Assignment', { - leftHandSide: buildNode('Identifier', { name: `${node.name}_${num_modifiers}`, subType: 'generalNumber' }), + leftHandSide: buildNode('Identifier', { name: `${node.name}_${num_modifiers}`, subType: 'generalNumber' }), operator: '=', rightHandSide: buildNode('Identifier', { name: `${node.name}`, subType: 'generalNumber' }) }); const newNode2 = buildNode('ExpressionStatement', { - expression: initInnerNode1, - interactsWithSecret: true, - isVarDec: true, + expression: initInnerNode1, + interactsWithSecret: true, + isVarDec: true, }); newNode2.outsideIf = true; - if (location.index !== -1) { - if (location.trueIndex !== -1) { - fnDefNode.node._newASTPointer.body.statements[location.index].trueBody.splice(location.trueIndex + 2, 0, newNode2); - } else if (location.falseIndex !== -1) { - fnDefNode.node._newASTPointer.body.statements[location.index].falseBody.splice(location.falseIndex + 2, 0, newNode2); - } else { - fnDefNode.node._newASTPointer.body.statements.splice(location.index + 2, 0, newNode2); - } + if (location.index!== -1) { + if (location.trueIndex !== -1){ fnDefNode.node._newASTPointer.body.statements[location.index].trueBody.splice(location.trueIndex + 2, 0, newNode2); } + else if (location.falseIndex !== -1){ fnDefNode.node._newASTPointer.body.statements[location.index].falseBody.splice(location.falseIndex + 2, 0, newNode2); } + else {fnDefNode.node._newASTPointer.body.statements.splice(location.index + 2, 0, newNode2);} } } } } } }); - - // Ensure correct name for the public variable + // We ensure here that the public variable used has the correct name, e.g index_2 instead of index. if (num_modifiers != 0) { if (IDnode.name === node.name){ IDnode.name += `_${num_modifiers}`; @@ -202,8 +187,8 @@ const publicVariables = (path: NodePath, state: any, IDnode: any) => { IDnode.name = `${node.name}_${num_modifiers}`; } } - - // Reset the original variable name to its initial value + // After the non-secret variables have been modified we need to reset the original variable name to its initial value. + // e.g. index = index_init. for (let i = fnDefNode.node._newASTPointer.body.statements.length - 1; i >= 0; i--) { const p = fnDefNode.node._newASTPointer.body.statements[i]; if (p.expression?.rightHandSide?.name === `${node.name}_init`) { @@ -211,39 +196,33 @@ const publicVariables = (path: NodePath, state: any, IDnode: any) => { } } const endNodeInit = buildNode('Assignment', { - leftHandSide: buildNode('Identifier', { name: `${node.name}`, subType: 'generalNumber' }), + leftHandSide: buildNode('Identifier', { name: `${node.name}`, subType: 'generalNumber' }), operator: '=', rightHandSide: buildNode('Identifier', { name: `${node.name}_init`, subType: 'generalNumber' }), }); const endNode = buildNode('ExpressionStatement', { - expression: endNodeInit, - interactsWithSecret: true, - isVarDec: false, + expression: endNodeInit, + interactsWithSecret: true, + isVarDec: false, }); endNode.isEndInit = true; fnDefNode.node._newASTPointer.body.statements.push(endNode); } + // We no longer need this because index expression nodes are not input. + //if (['Identifier', 'IndexAccess'].includes(node.indexExpression?.nodeType)) publicVariables(NodePath.getPath(node.indexExpression), state, null); } - //Visitor for publicVariables const publicVariablesVisitor = (thisPath: NodePath, thisState: any) => { const { node } = thisPath; let { name } = node; if (!['Identifier', 'IndexAccess'].includes(thisPath.nodeType)) return; - - const binding = thisPath.getReferencedBinding(node); - - - if ( binding instanceof VariableBinding && - (node.interactsWithPublic || node.baseExpression?.interactsWithPublic) && - !binding.isSecret && + if ( (binding instanceof VariableBinding) && !binding.isSecret && binding.stateVariable && thisPath.getAncestorContainedWithin('rightHandSide') ){ } else{ name = thisPath.scope.getIdentifierMappingKeyName(node); } - const newNode = buildNode( node.nodeType, { name, type: node.typeDescriptions?.typeString }, From dbf9f9abeca23fa9a22367e773622df9230439bd Mon Sep 17 00:00:00 2001 From: kkahina Date: Mon, 19 Aug 2024 10:47:20 +0100 Subject: [PATCH 14/25] removed bug --- privatekey | 8 -------- privatekey.pub | 1 - .../Non-Secret-Array-Incrementation.zol | 20 +++++++++++++++++++ 3 files changed, 20 insertions(+), 9 deletions(-) delete mode 100644 privatekey delete mode 100644 privatekey.pub create mode 100644 test/contracts/Non-Secret-Array-Incrementation.zol diff --git a/privatekey b/privatekey deleted file mode 100644 index 7197a0b7..00000000 --- a/privatekey +++ /dev/null @@ -1,8 +0,0 @@ ------BEGIN OPENSSH PRIVATE KEY----- -b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABASCLRvwc -n77yJFa5VzDXRKAAAAGAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIERVnHdjXuVDYprn -Qgq++Lv012NyXBzX+1Ea/6RUgvRGAAAAoB52MIATVWDsWlmsmifcL9SlGPmFw+Sh0qHacl -W/1BWDhEb2Wsz0TIiLx3ujAjAwKpRatROFkBM/BcA346oBGT01EtCMl+KNYSB2pYIp4Q4k -XAwR3lLVIjH1PNFOIyPL/FTHluYSSPpVdBINE9qa8Lq0cp4Rshru7MV9X74AP1Qddl9zNp -zxo/sLgwe7IkdxxGbJJgIzk4fAJC+rDUcjvtQ= ------END OPENSSH PRIVATE KEY----- diff --git a/privatekey.pub b/privatekey.pub deleted file mode 100644 index a1972aac..00000000 --- a/privatekey.pub +++ /dev/null @@ -1 +0,0 @@ -ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIERVnHdjXuVDYprnQgq++Lv012NyXBzX+1Ea/6RUgvRG kahina.khacef@uk.ey.com diff --git a/test/contracts/Non-Secret-Array-Incrementation.zol b/test/contracts/Non-Secret-Array-Incrementation.zol new file mode 100644 index 00000000..add58b75 --- /dev/null +++ b/test/contracts/Non-Secret-Array-Incrementation.zol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: CC0 +pragma solidity ^0.8.0; + +contract Assign { +secret uint256 private a; +secret uint256 private b; +mapping(uint256 => uint256) public c; + +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[0]; +} + +} \ No newline at end of file From a1603331a2fc048e709229dcf30bece6e1927397 Mon Sep 17 00:00:00 2001 From: kkahina Date: Mon, 19 Aug 2024 10:51:18 +0100 Subject: [PATCH 15/25] chore: updated a zol contract --- test/contracts/Arrays-input.zol | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/test/contracts/Arrays-input.zol b/test/contracts/Arrays-input.zol index 2385c9aa..4e4c9d15 100644 --- a/test/contracts/Arrays-input.zol +++ b/test/contracts/Arrays-input.zol @@ -5,14 +5,13 @@ pragma solidity ^0.8.0; contract Assign { secret uint256 private a; - - uint256[5] public b; + uint256[6] public b; function add(secret uint256[5] calldata value, uint256[5] calldata publicValue) public { b = publicValue; - for (uint256 index = 0; index < 5; index++) { - known a += value[index]; + for (uint256 index = 0; index < 6; index++) { + known a += value[index]; } } From 72c46dcc0a0fa340e0df9622a009579b403a1db0 Mon Sep 17 00:00:00 2001 From: kkahina Date: Mon, 19 Aug 2024 10:52:21 +0100 Subject: [PATCH 16/25] fix bug --- test/contracts/Non-Secret-Array.zol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/contracts/Non-Secret-Array.zol b/test/contracts/Non-Secret-Array.zol index b7bf68f9..4a11afa5 100644 --- a/test/contracts/Non-Secret-Array.zol +++ b/test/contracts/Non-Secret-Array.zol @@ -15,7 +15,7 @@ c[0] += value; function add1( uint256 value) public { require(index < c.length, "Index out of bounds"); c[0] += value; -known a += value; +known a += c[0]; } function add2( uint256 value) public { From 2f4018923e7051ab3290251989f78c0171b8b49a Mon Sep 17 00:00:00 2001 From: kkahina Date: Tue, 20 Aug 2024 10:28:53 +0100 Subject: [PATCH 17/25] valid syntax for array, still value --- .../visitors/toContractVisitor.ts | 1 + .../visitors/toOrchestrationVisitor.ts | 62 +++++++++++-------- test/contracts/Non-Secret-Array.zol | 7 +-- 3 files changed, 41 insertions(+), 29 deletions(-) diff --git a/src/transformers/visitors/toContractVisitor.ts b/src/transformers/visitors/toContractVisitor.ts index 6e740950..c43fc69e 100644 --- a/src/transformers/visitors/toContractVisitor.ts +++ b/src/transformers/visitors/toContractVisitor.ts @@ -59,6 +59,7 @@ const findCustomInputsVisitor = (thisPath: NodePath, thisState: any) => { ) { thisState.customInputs ??= []; const type = binding.node.typeName.nodeType === 'Mapping' ? binding.node.typeName.valueType.name : binding.node.typeName.name; + const isConstantArray = thisPath.isConstantArray(); const arrayLength = isConstantArray && thisPath.node.typeName?.length ? thisPath.node.typeName.length.value : false; diff --git a/src/transformers/visitors/toOrchestrationVisitor.ts b/src/transformers/visitors/toOrchestrationVisitor.ts index 02de3e0e..5e8b40db 100644 --- a/src/transformers/visitors/toOrchestrationVisitor.ts +++ b/src/transformers/visitors/toOrchestrationVisitor.ts @@ -115,28 +115,37 @@ const findStatementId = (statements: any, ID: number) => { // i.e. public 'accessed' variables const addPublicInput = (path: NodePath, state: any, IDnode: any) => { const { node } = path; + + console.log("print node", node); let { name } = path.scope.getReferencedIndicator(node, true) || path.node; +// if (name.includes('[') && name.includes(']')) { +// name = name.replace(/\[|\]/g, '_'); +// } +name = name.replace(/\[([^\]]+)\]/g, '_$1'); + +// Ensure there is no trailing underscore +if (name.endsWith('_')) { + name = name.slice(0, -1); +} + console.log("display name",name); -let num_modifiers=0; +// let num_modifiers=0; -if (IDnode) { - if (num_modifiers !== 0) { - if (IDnode.name === node.name) { - IDnode.name += `_${num_modifiers}`; - } else { - IDnode.name = `${node.name}_${num_modifiers}`; - } - } else { - IDnode.name = name; // Just set the name if no modifiers - } -} else { - return; -} +// if (IDnode) { +// if (num_modifiers !== 0) { +// if (IDnode.name === node.name) { +// IDnode.name += `_${num_modifiers}`; +// } else { +// IDnode.name = `${node.name}_${num_modifiers}`; +// } +// } +// } -if (!node.baseExpression || !node.baseExpression.interactsWithPublic){ - return; -} +// if (!node.baseExpression || !node.baseExpression.interactsWithPublic){ +// return; + +// } const binding = path.getReferencedBinding(node); if (!['Identifier', 'IndexAccess'].includes(path.nodeType)) return; @@ -209,7 +218,7 @@ if (!node.baseExpression || !node.baseExpression.interactsWithPublic){ const statements = fnDefNode.node._newASTPointer.body.statements; - // let num_modifiers=0; + let num_modifiers=0; // For each statement that modifies the public variable previously, we need to ensure that the modified variable is stored for later. // We also need that the original public variable is updated, e.g if the statement is index_2 = index +1, we need an extra statement index = index_2. modifiedBeforePaths?.forEach((p: NodePath) => { @@ -329,13 +338,16 @@ if (!node.baseExpression || !node.baseExpression.interactsWithPublic){ }); //We ensure here that the public variable used has the correct name, e.g index_2 instead of index. - // if (num_modifiers != 0) { - // if (IDnode.name === node.name){ - // IDnode.name += `_${num_modifiers}`; - // } else { - // IDnode.name = `${node.name}_${num_modifiers}`; - // } - // } + if(IDnode) { + if (num_modifiers != 0) { + if (IDnode.name === node.name){ + IDnode.name += `_${num_modifiers}`; + } else { + IDnode.name = `${node.name}_${num_modifiers}`; + } + } + } + // After the non-secret variables have been modified we need to reset the original variable name to its initial value. // e.g. index = index_init. if (node.nodeType !== 'IndexAccess') { diff --git a/test/contracts/Non-Secret-Array.zol b/test/contracts/Non-Secret-Array.zol index 4a11afa5..420a8ceb 100644 --- a/test/contracts/Non-Secret-Array.zol +++ b/test/contracts/Non-Secret-Array.zol @@ -9,13 +9,12 @@ uint256[3] public c; function add( uint256 value) public { -c[0] += value; +c[index] += value; } function add1( uint256 value) public { -require(index < c.length, "Index out of bounds"); -c[0] += value; -known a += c[0]; +c[index] += value; +known a += c[index]; } function add2( uint256 value) public { From ec137fd034e3ef20b1c5b4d54d8dd2ea094c4a2f Mon Sep 17 00:00:00 2001 From: kkahina Date: Wed, 28 Aug 2024 14:24:01 +0100 Subject: [PATCH 18/25] fixed input params --- .../orchestration/nodejs/toOrchestration.ts | 22 +++- .../checks/interactsWithSecretVisitor.ts | 36 ++++++ src/transformers/visitors/toCircuitVisitor.ts | 2 +- .../visitors/toOrchestrationVisitor.ts | 112 +++++++++++++----- 4 files changed, 138 insertions(+), 34 deletions(-) diff --git a/src/codeGenerators/orchestration/nodejs/toOrchestration.ts b/src/codeGenerators/orchestration/nodejs/toOrchestration.ts index 9a432fde..a6495a2f 100644 --- a/src/codeGenerators/orchestration/nodejs/toOrchestration.ts +++ b/src/codeGenerators/orchestration/nodejs/toOrchestration.ts @@ -24,9 +24,9 @@ const getAccessedValue = (name: string) => { */ const getPublicValue = (node: any) => { if (node.nodeType !== 'IndexAccess') - // In the _init variable we save the initial value of the variable for use later. + // In the _init variable we save the initial value of the variable for use later. return `\nlet ${node.name} = generalise(await instance.methods.${codeGenerator(node)}().call());\n let ${node.name}_init = ${node.name};`; - return `\nconst ${node.name} = generalise(await instance.methods.${codeGenerator(node.baseExpression, { lhs: true} )}(${codeGenerator(node.indexExpression, { contractCall: true })}).call());`; + return `\nlet ${node.name} = generalise(await instance.methods.${codeGenerator(node.baseExpression, { lhs: true} )}(${codeGenerator(node.indexExpression, { contractCall: true })}).call()); \n let ${node.name}_init = ${node.name}`; }; /** @@ -127,16 +127,21 @@ export default function codeGenerator(node: any, options: any = {}): any { case 'ExpressionStatement': if (!node.incrementsSecretState && (node.interactsWithSecret || node.expression?.internalFunctionInteractsWithSecret)){ return `\n${codeGenerator(node.expression)};`; + } - if (node.incrementsSecretState && (node.interactsWithSecret || node.expression?.internalFunctionInteractsWithSecret)){ + + if (node.incrementsSecretState && (node.interactsWithSecret ||node.containsPublic || node.expression?.internalFunctionInteractsWithSecret)){ let privateStateName = node.privateStateName.replace(/\./g, '_'); let increments; + if (node.expression.operator === '+='){ 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_inc = generalise(parseInt(${privateStateName}_newCommitmentValue_inc.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`; @@ -166,18 +171,24 @@ export default function codeGenerator(node: any, options: any = {}): any { return " "; case 'Assignment': - // To ensure the left hand side is always a general number, we generalise it here (excluding the initialisation in a for loop). + // To ensure the left hand side is always a general number, we generalise it here (excluding the initialisation in a for loop). + if (!node.isInitializationAssignment && node.rightHandSide.subType !== 'generalNumber'){ if (['+=', '-=', '*='].includes(node.operator)) { + return `${codeGenerator(node.leftHandSide, { lhs: true, })} = generalise(${codeGenerator(node.leftHandSide)} ${node.operator.charAt( 0, )} ${codeGenerator(node.rightHandSide)})`; + } + + return `${codeGenerator(node.leftHandSide, { lhs: true })} ${ node.operator } generalise(${codeGenerator(node.rightHandSide)})`; + } else { if (['+=', '-=', '*='].includes(node.operator)) { return `${codeGenerator(node.leftHandSide, { @@ -189,7 +200,10 @@ export default function codeGenerator(node: any, options: any = {}): any { return `${codeGenerator(node.leftHandSide, { lhs: true })} ${ node.operator } ${codeGenerator(node.rightHandSide)}`; + } + + case 'BinaryOperation': diff --git a/src/transformers/visitors/checks/interactsWithSecretVisitor.ts b/src/transformers/visitors/checks/interactsWithSecretVisitor.ts index 3bea6a78..9b70ba07 100644 --- a/src/transformers/visitors/checks/interactsWithSecretVisitor.ts +++ b/src/transformers/visitors/checks/interactsWithSecretVisitor.ts @@ -34,6 +34,31 @@ const markSubtreeInteractsWithPublic = (thisPath: any, thisState: any) => { indicator.addPublicInteractingPath(thisState.publicPath); }; +const markIndicatorSubtreeInteractsWithSecret = (thisPath: any, thisState: any) => { + const { node, scope } = thisPath; + if (!['Identifier', 'VariableDeclarationStatement'].includes(node.nodeType)) + return; + const indicator = scope.getReferencedIndicator(node, true); + // we don't want to add itself as an interacted with path + if (indicator && thisState.secretPath.node.id !== node.id) + indicator.addSecretInteractingPath(thisState.secretPath); +}; + +const interactwithPublicSecret = (thisPath: any, thisState: any) => { + const { node, scope } = thisPath; + + + if (node.nodeType === 'ExpressionStatement') { + const leftHandSideIndicator = scope.getReferencedIndicator(node.expression.leftHandSide, true); + + if (leftHandSideIndicator?.interactsWithSecret) { + thisPath.traversePathsFast(markIndicatorSubtreeInteractsWithSecret, { + secretPath: thisPath, + }); + } + } +}; + export default { FunctionCall: { @@ -50,6 +75,17 @@ export default { }, }, + FunctionDefinition: { + exit(path: NodePath) { + + path.traversePathsFast(interactwithPublicSecret, { + publicPath: path, + }); + + + }, + }, + Identifier: { exit(path: NodePath) { const { node, scope } = path; diff --git a/src/transformers/visitors/toCircuitVisitor.ts b/src/transformers/visitors/toCircuitVisitor.ts index db99291a..1aea3d5b 100644 --- a/src/transformers/visitors/toCircuitVisitor.ts +++ b/src/transformers/visitors/toCircuitVisitor.ts @@ -1090,7 +1090,7 @@ const visitor = { state.skipSubNodes = true; return; } - let interactsWithSecret = false ; + let interactsWithSecret = scope.getReferencedIndicator(node)?.interactsWithSecret ; scope.bindings[node.id].referencingPaths.forEach(refPath => { const newState: any = {}; refPath.parentPath.traversePathsFast( diff --git a/src/transformers/visitors/toOrchestrationVisitor.ts b/src/transformers/visitors/toOrchestrationVisitor.ts index 5e8b40db..8ee74ac3 100644 --- a/src/transformers/visitors/toOrchestrationVisitor.ts +++ b/src/transformers/visitors/toOrchestrationVisitor.ts @@ -116,7 +116,6 @@ const findStatementId = (statements: any, ID: number) => { const addPublicInput = (path: NodePath, state: any, IDnode: any) => { const { node } = path; - console.log("print node", node); let { name } = path.scope.getReferencedIndicator(node, true) || path.node; // if (name.includes('[') && name.includes(']')) { // name = name.replace(/\[|\]/g, '_'); @@ -127,25 +126,6 @@ name = name.replace(/\[([^\]]+)\]/g, '_$1'); if (name.endsWith('_')) { name = name.slice(0, -1); } - console.log("display name",name); - -// let num_modifiers=0; - -// if (IDnode) { -// if (num_modifiers !== 0) { -// if (IDnode.name === node.name) { -// IDnode.name += `_${num_modifiers}`; -// } else { -// IDnode.name = `${node.name}_${num_modifiers}`; -// } -// } -// } - - -// if (!node.baseExpression || !node.baseExpression.interactsWithPublic){ -// return; - -// } const binding = path.getReferencedBinding(node); if (!['Identifier', 'IndexAccess'].includes(path.nodeType)) return; @@ -166,10 +146,12 @@ if (name.endsWith('_')) { (node.interactsWithPublic || node.baseExpression?.interactsWithPublic || isCondition || isForCondition || isInitializationExpression || isLoopExpression) && binding.stateVariable && !binding.isSecret ) { + + const fnDefNode = path.getAncestorOfType('FunctionDefinition'); if (!fnDefNode) throw new Error(`Not in a function`); let innerNode: any; - if (path.isMapping(node)) { + if (path.isMapping(node) || (node.nodeType === 'IndexAccess' && node.baseExpression.nodeType === 'Identifier')) { name = getIndexAccessName(node); node.name = name; let indexExpressionNode: any; @@ -181,7 +163,8 @@ if (name.endsWith('_')) { indexExpressionNode = buildNode(node.indexExpression.nodeType, { name: node.indexExpression.name, value: node.indexExpression.value, - subType: node.indexExpression.typeDescriptions?.typeString,}); + subType: node.indexExpression.typeDescriptions?.typeString,}); + innerNode = buildNode('IndexAccess', { name, baseExpression: buildNode('Identifier', { name: node.baseExpression.name }), @@ -189,7 +172,9 @@ if (name.endsWith('_')) { isAccessed: true, isSecret: false, }) - } else { + } + + else { innerNode = buildNode('VariableDeclaration', { name, isAccessed: true, @@ -217,6 +202,7 @@ if (name.endsWith('_')) { const modifiedBeforePaths = path.scope.getReferencedIndicator(node, true)?.modifyingPaths?.filter((p: NodePath) => p.node.id < node.id); const statements = fnDefNode.node._newASTPointer.body.statements; + let num_modifiers=0; // For each statement that modifies the public variable previously, we need to ensure that the modified variable is stored for later. @@ -233,6 +219,7 @@ if (name.endsWith('_')) { // we have to go back and mark any editing statements as interactsWithSecret so they show up expNode.interactsWithSecret = true; const moveExpNode = cloneDeep(expNode); + // We now move the statement in expNode to preStatements. //If the statement is within an if statement we need to find the correct if statement in preStatements or create a new one. let ifPreIndex = null; @@ -265,7 +252,7 @@ if (name.endsWith('_')) { if ((statements[location.index]?.trueBody && statements[location.index].trueBody.every(element => element === null || element === undefined)) && (statements[location.index]?.falseBody && statements[location.index].falseBody.every(element => element === null || element === undefined))) { delete statements[location.index]; } - + if( (expNode.expression && expNode.expression.leftHandSide && expNode.expression.leftHandSide?.name === node.name) || (expNode.initialValue && expNode.initialValue.leftHandSide && expNode.initialValue.leftHandSide?.name === node.name) @@ -277,11 +264,17 @@ if (name.endsWith('_')) { 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, @@ -305,6 +298,7 @@ if (name.endsWith('_')) { expression: InnerNode, interactsWithSecret: true, }); + if (location.trueIndex !== -1){ fnDefNode.node._newASTPointer.body.preStatements[ifPreIndex].trueBody.push(newNode1); } else if (location.falseIndex !== -1){ fnDefNode.node._newASTPointer.body.preStatements[ifPreIndex].falseBody.push(newNode1); } else {fnDefNode.node._newASTPointer.body.preStatements.push(newNode1);} @@ -332,15 +326,18 @@ if (name.endsWith('_')) { else if (location.falseIndex !== -1){ fnDefNode.node._newASTPointer.body.preStatements[ifPreIndex].falseBody.push(newNode2); } else {fnDefNode.node._newASTPointer.body.preStatements.push(newNode2);} } + } } } }); - + + //We ensure here that the public variable used has the correct name, e.g index_2 instead of index. if(IDnode) { if (num_modifiers != 0) { if (IDnode.name === node.name){ + console.log(`IDnode name (${IDnode.name}) is the same as node name (${node.name})`); IDnode.name += `_${num_modifiers}`; } else { IDnode.name = `${node.name}_${num_modifiers}`; @@ -348,9 +345,9 @@ if (name.endsWith('_')) { } } + // After the non-secret variables have been modified we need to reset the original variable name to its initial value. // e.g. index = index_init. - if (node.nodeType !== 'IndexAccess') { fnDefNode.node._newASTPointer.body.preStatements = fnDefNode.node._newASTPointer.body.preStatements.filter(p => p.expression?.rightHandSide?.name !== `${node.name}_init`); const endNodeInit = buildNode('Assignment', { leftHandSide: buildNode('Identifier', { name: `${node.name}`, subType: 'generalNumber' }), @@ -361,8 +358,8 @@ if (name.endsWith('_')) { expression: endNodeInit, interactsWithSecret: true, }); + fnDefNode.node._newASTPointer.body.preStatements.push(endNode); - } // if the node is the indexExpression, we dont need its value in the circuit state.publicInputs ??= []; @@ -1387,7 +1384,6 @@ const visitor = { leftHandSide, rightHandSide: binOpNode, }); - binOpNode.leftExpression.name = path.node.leftHandSide.name; return assNode; }; @@ -1405,6 +1401,7 @@ const visitor = { parent._newASTPointer.expression = newNode; } } + if (path.getAncestorContainedWithin('initializationExpression') && parent._newASTPointer.nodeType === 'VariableDeclarationStatement' ){ parent._newASTPointer.initialValue.isInitializationAssignment = true; } else if (path.getAncestorContainedWithin('initializationExpression')) { @@ -1413,6 +1410,60 @@ const visitor = { // node._newASTPointer = newNode; // no need to ascribe the node._newASTPointer, because we're exiting. }, }, + // Assignment: { + // enter(path: NodePath) { + // const { node, parent } = path; + // const newNode = buildNode(node.nodeType, { operator: node.operator }); + // node._newASTPointer = newNode; + + // if (parent._newASTPointer.nodeType === 'VariableDeclarationStatement') { + // parent._newASTPointer.initialValue = newNode; + // } else { + // parent._newASTPointer.expression = newNode; + // } + // }, + + // exit(path: NodePath) { + // // Convert 'a += b' into 'a = a + b' for all operators + // const expandAssignment = (node: any) => { + // const { operator, leftHandSide, rightHandSide } = node; + // const expandableOps = ['+=', '-=', '*=', '/=', '%=', '|=', '&=', '^=']; + // if (!expandableOps.includes(operator)) return node; + // const op = operator.charAt(0); + // const binOpNode = buildNode('BinaryOperation', { + // operator: op, + // leftExpression: cloneDeep(leftHandSide), + // rightExpression: rightHandSide, + // }); + // const assNode = buildNode('Assignment', { + // operator: '=', + // leftHandSide, + // rightHandSide: binOpNode, + // }); + // return assNode; + // }; + + // const { parent } = path; + // const binding = path.getReferencedBinding(path.node.leftHandSide); + // if (binding instanceof VariableBinding && !binding.isSecret && binding.stateVariable) { + // if (parent._newASTPointer.nodeType === 'VariableDeclarationStatement') { + // const circuitNode = parent._newASTPointer.initialValue; + // const newNode = expandAssignment(circuitNode); + // parent._newASTPointer.initialValue = newNode; + // } else { + // const circuitNode = parent._newASTPointer.expression; + // const newNode = expandAssignment(circuitNode); + // parent._newASTPointer.expression = newNode; + // } + // } + // if (path.getAncestorContainedWithin('initializationExpression') && parent._newASTPointer.nodeType === 'VariableDeclarationStatement') { + // parent._newASTPointer.initialValue.isInitializationAssignment = true; + // } else if (path.getAncestorContainedWithin('initializationExpression')) { + // parent._newASTPointer.expression.isInitializationAssignment = true; + // } + // }, + // }, + TupleExpression: { enter(path: NodePath, state: any) { @@ -1607,6 +1658,7 @@ const visitor = { //|| indicator?.interactsWithSecret, oldASTId: node.id, }); + node._newASTPointer = newNode; if (Array.isArray(parent._newASTPointer) || (!path.isInSubScope() && Array.isArray(parent._newASTPointer[path.containerName]))) { parent._newASTPointer.push(newNode); @@ -1619,6 +1671,7 @@ const visitor = { exit(path: NodePath, state: any) { const { node, scope } = path; + const { leftHandSide: lhs } = node.expression; const indicator = scope.getReferencedIndicator(lhs, true); let name = indicator?.isMapping @@ -1852,10 +1905,11 @@ const visitor = { name, subType: node.typeDescriptions.typeString, }); + + // if this is a public state variable, this fn will add a public input addPublicInput(path, state, null); state.skipSubNodes = true; // the subnodes are baseExpression and indexExpression - we skip them - parent._newASTPointer[path.containerName] = newNode; }, From a201273d7558be6e7e6e3481a28b2fb117ebc4b5 Mon Sep 17 00:00:00 2001 From: kkahina Date: Thu, 29 Aug 2024 17:25:48 +0100 Subject: [PATCH 19/25] fixe cuntomInput addIpnput --- .../solidity/nodes/FunctionBoilerplateGenerator.ts | 2 +- .../solidity/raw/FunctionBoilerplateGenerator.ts | 1 + .../javascript/raw/toOrchestration.ts | 8 ++++++++ .../orchestration/nodejs/toOrchestration.ts | 3 --- .../visitors/checks/interactsWithSecretVisitor.ts | 6 +----- .../visitors/toOrchestrationVisitor.ts | 14 +++++++++++--- test/contracts/Arrays.zol | 7 +++---- test/contracts/Non-Secret-Array.zol | 8 -------- 8 files changed, 25 insertions(+), 24 deletions(-) diff --git a/src/boilerplate/contract/solidity/nodes/FunctionBoilerplateGenerator.ts b/src/boilerplate/contract/solidity/nodes/FunctionBoilerplateGenerator.ts index d19e7877..3b95cb4a 100644 --- a/src/boilerplate/contract/solidity/nodes/FunctionBoilerplateGenerator.ts +++ b/src/boilerplate/contract/solidity/nodes/FunctionBoilerplateGenerator.ts @@ -98,7 +98,7 @@ class FunctionBoilerplateGenerator { }); return { structName: structDef.name, properties: names, isParam: path.isFunctionParameter(node), isConstantArray: path.isConstantArray(node) ? node.typeName.length.value : false, inCircuit: node.interactsWithSecret }; } - return { name: node.name, type: node.typeName.name || node.typeName.baseType?.name || node.typeName.pathNode?.name, isParam: path.isFunctionParameter(node), isConstantArray: path.isConstantArray(node) ? node.typeName.length.value : false, inCircuit: node.interactsWithSecret }; + return { name: node.name, type: node.typeName.name || node.typeName.baseType?.name || node.typeName.pathNode?.name, isParam: path.isFunctionParameter(node), isConstantArray: path.isConstantArray(node) ? node.typeName.length.value : false, inCircuit: node.interactsWithSecret || scope.getReferencedIndicator(node).interactsWithSecret }; } const params = path.getFunctionParameters(); diff --git a/src/boilerplate/contract/solidity/raw/FunctionBoilerplateGenerator.ts b/src/boilerplate/contract/solidity/raw/FunctionBoilerplateGenerator.ts index 39c54d20..1eb2e925 100644 --- a/src/boilerplate/contract/solidity/raw/FunctionBoilerplateGenerator.ts +++ b/src/boilerplate/contract/solidity/raw/FunctionBoilerplateGenerator.ts @@ -86,6 +86,7 @@ class FunctionBoilerplateGenerator { } if (input.structName) customInputs[i] = input.properties; }); + console.log('cutomInputs in contract', customInputs); let msgSigCheck = ([...(isConstructor ? [] : [`bytes4 sig = bytes4(keccak256("${functionName}(${parameter})")) ; \n \t \t \t if (sig == msg.sig)`])]); customInputs = customInputs?.flat(Infinity).filter(p => (p.inCircuit || p.isReturn)); diff --git a/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts b/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts index 1f4c1903..a843dd7a 100644 --- a/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts +++ b/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts @@ -160,12 +160,17 @@ export const generateProofBoilerplate = (node: any) => { ? [`\n\t\t\t\t\t\t\t\t${stateName}_stateVarId_key.integer,`] : []; // we add any extra params the circuit needs + console.log('Node Parameters Before Filtering:', node.parameters); node.parameters + .filter( (para: string) => !privateStateNames.includes(para) && ( !output.join().includes(`${para}.integer`) && !output.join().includes('msgValue')), ) + + + ?.forEach((param: string) => { if (param == 'msgSender') { parameters.unshift(`\t${param}.integer,`); @@ -176,8 +181,10 @@ export const generateProofBoilerplate = (node: any) => { else { parameters.push(`\t${param}.integer,`); } + console.log('Rania@@@@@@@@@@@@@@@@@@@@@@',param) }); + // then we build boilerplate code per state switch (stateNode.isWhole) { case true: @@ -238,6 +245,7 @@ export const generateProofBoilerplate = (node: any) => { isSharedSecret: stateNode.isSharedSecret, parameters, }) + ); containsNullifierRoot = true; containsNewNullifierRoot = true; diff --git a/src/codeGenerators/orchestration/nodejs/toOrchestration.ts b/src/codeGenerators/orchestration/nodejs/toOrchestration.ts index a6495a2f..aef4b9c3 100644 --- a/src/codeGenerators/orchestration/nodejs/toOrchestration.ts +++ b/src/codeGenerators/orchestration/nodejs/toOrchestration.ts @@ -127,7 +127,6 @@ export default function codeGenerator(node: any, options: any = {}): any { case 'ExpressionStatement': if (!node.incrementsSecretState && (node.interactsWithSecret || node.expression?.internalFunctionInteractsWithSecret)){ return `\n${codeGenerator(node.expression)};`; - } if (node.incrementsSecretState && (node.interactsWithSecret ||node.containsPublic || node.expression?.internalFunctionInteractsWithSecret)){ @@ -203,8 +202,6 @@ export default function codeGenerator(node: any, options: any = {}): any { } - - case 'BinaryOperation': return `${codeGenerator(node.leftExpression, { lhs: options.condition })} ${ diff --git a/src/transformers/visitors/checks/interactsWithSecretVisitor.ts b/src/transformers/visitors/checks/interactsWithSecretVisitor.ts index 9b70ba07..118b4b14 100644 --- a/src/transformers/visitors/checks/interactsWithSecretVisitor.ts +++ b/src/transformers/visitors/checks/interactsWithSecretVisitor.ts @@ -46,8 +46,6 @@ const markIndicatorSubtreeInteractsWithSecret = (thisPath: any, thisState: any) const interactwithPublicSecret = (thisPath: any, thisState: any) => { const { node, scope } = thisPath; - - if (node.nodeType === 'ExpressionStatement') { const leftHandSideIndicator = scope.getReferencedIndicator(node.expression.leftHandSide, true); @@ -59,6 +57,7 @@ const interactwithPublicSecret = (thisPath: any, thisState: any) => { } }; + export default { FunctionCall: { @@ -77,12 +76,9 @@ export default { FunctionDefinition: { exit(path: NodePath) { - path.traversePathsFast(interactwithPublicSecret, { publicPath: path, }); - - }, }, diff --git a/src/transformers/visitors/toOrchestrationVisitor.ts b/src/transformers/visitors/toOrchestrationVisitor.ts index 8ee74ac3..18fce989 100644 --- a/src/transformers/visitors/toOrchestrationVisitor.ts +++ b/src/transformers/visitors/toOrchestrationVisitor.ts @@ -214,6 +214,7 @@ if (name.endsWith('_')) { if (path.containerName !== 'indexExpression') { num_modifiers++; } + //console.log('expNode!!!!!!!!!!!!!!!!!',expNode); if (expNode) { // if the public input is modified before here, it won't show up in the mjs file // we have to go back and mark any editing statements as interactsWithSecret so they show up @@ -337,18 +338,20 @@ if (name.endsWith('_')) { if(IDnode) { if (num_modifiers != 0) { if (IDnode.name === node.name){ - console.log(`IDnode name (${IDnode.name}) is the same as node name (${node.name})`); IDnode.name += `_${num_modifiers}`; } else { IDnode.name = `${node.name}_${num_modifiers}`; } + console.log('aaaaaaaaaabbbbbbbbbbbbb', IDnode); } } // After the non-secret variables have been modified we need to reset the original variable name to its initial value. // e.g. index = index_init. + fnDefNode.node._newASTPointer.body.preStatements = fnDefNode.node._newASTPointer.body.preStatements.filter(p => p.expression?.rightHandSide?.name !== `${node.name}_init`); + const endNodeInit = buildNode('Assignment', { leftHandSide: buildNode('Identifier', { name: `${node.name}`, subType: 'generalNumber' }), operator: '=', @@ -365,6 +368,7 @@ if (name.endsWith('_')) { state.publicInputs ??= []; if (!(path.containerName === 'indexExpression' && !(path.parentPath.isSecret|| path.parent.containsSecret))) state.publicInputs.push(node); } + //console.log('Public Inputs After Addition aaaaaaaaaaaaaaaaaaaaaaaaaaaa:', state.publicInputs); if (['Identifier', 'IndexAccess'].includes(node.indexExpression?.nodeType)) addPublicInput(NodePath.getPath(node.indexExpression), state, null); } @@ -987,7 +991,11 @@ const visitor = { // this adds other values we need in the circuit for (const param of node._newASTPointer.parameters.parameters) { - if (param.isPrivate || param.isSecret || param.interactsWithSecret) { + + scope.getReferencedIndicator(param); + console.log('KKKKKKKKKKKKKK param', scope.getReferencedIndicator(param).interactsWithSecret); + + if (param.isPrivate || param.isSecret || param.interactsWithSecret || scope.getReferencedIndicator(param).interactsWithSecret) { if (param.typeName.isStruct) { param.typeName.properties.forEach((prop: any) => { newNodes.generateProofNode.parameters.push(`${param.name}.${prop.name}${param.typeName.isConstantArray ? '.all' : ''}`); @@ -1908,7 +1916,7 @@ const visitor = { // if this is a public state variable, this fn will add a public input - addPublicInput(path, state, null); + addPublicInput(path, state, newNode); state.skipSubNodes = true; // the subnodes are baseExpression and indexExpression - we skip them parent._newASTPointer[path.containerName] = newNode; }, diff --git a/test/contracts/Arrays.zol b/test/contracts/Arrays.zol index 8f83d200..9d5c5168 100644 --- a/test/contracts/Arrays.zol +++ b/test/contracts/Arrays.zol @@ -12,10 +12,9 @@ contract Assign { function add(secret uint256 value) public { - known a += value; - b[index] = 0; - index++; - b[index] = value; + + b[index] += value; + a += b[index]; } function remove(secret uint256 value) public { diff --git a/test/contracts/Non-Secret-Array.zol b/test/contracts/Non-Secret-Array.zol index 420a8ceb..0bf83af6 100644 --- a/test/contracts/Non-Secret-Array.zol +++ b/test/contracts/Non-Secret-Array.zol @@ -7,19 +7,11 @@ secret uint256 private b; uint256 public index; uint256[3] public c; -function add( uint256 value) public { -c[index] += value; -} function add1( uint256 value) public { c[index] += value; known a += c[index]; } -function add2( uint256 value) public { - -c[index] += value; -known a += value; -} } \ No newline at end of file From 20b44e4423755bad399f67fadf6b6c218ed23e94 Mon Sep 17 00:00:00 2001 From: kkahina Date: Thu, 29 Aug 2024 17:28:43 +0100 Subject: [PATCH 20/25] fixe Arrays.zol --- test/contracts/Arrays.zol | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/contracts/Arrays.zol b/test/contracts/Arrays.zol index 9d5c5168..8f83d200 100644 --- a/test/contracts/Arrays.zol +++ b/test/contracts/Arrays.zol @@ -12,9 +12,10 @@ contract Assign { function add(secret uint256 value) public { - - b[index] += value; - a += b[index]; + known a += value; + b[index] = 0; + index++; + b[index] = value; } function remove(secret uint256 value) public { From 54878a0e8fa1c8440741fd31a67c8de2ed844353 Mon Sep 17 00:00:00 2001 From: kkahina Date: Fri, 30 Aug 2024 15:02:14 +0100 Subject: [PATCH 21/25] fixe Arrays-Input --- .../nodes/FunctionBoilerplateGenerator.ts | 2 +- .../raw/FunctionBoilerplateGenerator.ts | 1 - .../javascript/raw/toOrchestration.ts | 2 -- .../visitors/toOrchestrationVisitor.ts | 17 ++++++----- src/traverse/NodePath.ts | 11 +++++++ src/traverse/Scope.ts | 29 ++++++++++++------- test/contracts/Arrays-input.zol | 2 +- 7 files changed, 41 insertions(+), 23 deletions(-) diff --git a/src/boilerplate/contract/solidity/nodes/FunctionBoilerplateGenerator.ts b/src/boilerplate/contract/solidity/nodes/FunctionBoilerplateGenerator.ts index 3b95cb4a..abd6d1ea 100644 --- a/src/boilerplate/contract/solidity/nodes/FunctionBoilerplateGenerator.ts +++ b/src/boilerplate/contract/solidity/nodes/FunctionBoilerplateGenerator.ts @@ -98,7 +98,7 @@ class FunctionBoilerplateGenerator { }); return { structName: structDef.name, properties: names, isParam: path.isFunctionParameter(node), isConstantArray: path.isConstantArray(node) ? node.typeName.length.value : false, inCircuit: node.interactsWithSecret }; } - return { name: node.name, type: node.typeName.name || node.typeName.baseType?.name || node.typeName.pathNode?.name, isParam: path.isFunctionParameter(node), isConstantArray: path.isConstantArray(node) ? node.typeName.length.value : false, inCircuit: node.interactsWithSecret || scope.getReferencedIndicator(node).interactsWithSecret }; + return { name: node.name, type: node.typeName.name || node.typeName.baseType?.name || node.typeName.pathNode?.name, isParam: path.isFunctionParameter(node), isConstantArray: path.isConstantArray(node) ? node.typeName.length.value : false, inCircuit: node.interactsWithSecret || scope.getReferencedIndicator(node)?.interactsWithSecret }; } const params = path.getFunctionParameters(); diff --git a/src/boilerplate/contract/solidity/raw/FunctionBoilerplateGenerator.ts b/src/boilerplate/contract/solidity/raw/FunctionBoilerplateGenerator.ts index 1eb2e925..39c54d20 100644 --- a/src/boilerplate/contract/solidity/raw/FunctionBoilerplateGenerator.ts +++ b/src/boilerplate/contract/solidity/raw/FunctionBoilerplateGenerator.ts @@ -86,7 +86,6 @@ class FunctionBoilerplateGenerator { } if (input.structName) customInputs[i] = input.properties; }); - console.log('cutomInputs in contract', customInputs); let msgSigCheck = ([...(isConstructor ? [] : [`bytes4 sig = bytes4(keccak256("${functionName}(${parameter})")) ; \n \t \t \t if (sig == msg.sig)`])]); customInputs = customInputs?.flat(Infinity).filter(p => (p.inCircuit || p.isReturn)); diff --git a/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts b/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts index a843dd7a..03a9fd6d 100644 --- a/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts +++ b/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts @@ -160,7 +160,6 @@ export const generateProofBoilerplate = (node: any) => { ? [`\n\t\t\t\t\t\t\t\t${stateName}_stateVarId_key.integer,`] : []; // we add any extra params the circuit needs - console.log('Node Parameters Before Filtering:', node.parameters); node.parameters .filter( @@ -181,7 +180,6 @@ export const generateProofBoilerplate = (node: any) => { else { parameters.push(`\t${param}.integer,`); } - console.log('Rania@@@@@@@@@@@@@@@@@@@@@@',param) }); diff --git a/src/transformers/visitors/toOrchestrationVisitor.ts b/src/transformers/visitors/toOrchestrationVisitor.ts index 18fce989..aed1d936 100644 --- a/src/transformers/visitors/toOrchestrationVisitor.ts +++ b/src/transformers/visitors/toOrchestrationVisitor.ts @@ -214,7 +214,6 @@ if (name.endsWith('_')) { if (path.containerName !== 'indexExpression') { num_modifiers++; } - //console.log('expNode!!!!!!!!!!!!!!!!!',expNode); if (expNode) { // if the public input is modified before here, it won't show up in the mjs file // we have to go back and mark any editing statements as interactsWithSecret so they show up @@ -342,7 +341,6 @@ if (name.endsWith('_')) { } else { IDnode.name = `${node.name}_${num_modifiers}`; } - console.log('aaaaaaaaaabbbbbbbbbbbbb', IDnode); } } @@ -368,8 +366,7 @@ if (name.endsWith('_')) { state.publicInputs ??= []; if (!(path.containerName === 'indexExpression' && !(path.parentPath.isSecret|| path.parent.containsSecret))) state.publicInputs.push(node); } - //console.log('Public Inputs After Addition aaaaaaaaaaaaaaaaaaaaaaaaaaaa:', state.publicInputs); - + if (['Identifier', 'IndexAccess'].includes(node.indexExpression?.nodeType)) addPublicInput(NodePath.getPath(node.indexExpression), state, null); } /** @@ -990,12 +987,16 @@ const visitor = { } // this adds other values we need in the circuit + for (const param of node._newASTPointer.parameters.parameters) { + let oldParam : any ; + for(const para of node.parameters.parameters) { + if ( para?.name === param?.name ) + oldParam = para ; + break; + } - scope.getReferencedIndicator(param); - console.log('KKKKKKKKKKKKKK param', scope.getReferencedIndicator(param).interactsWithSecret); - - if (param.isPrivate || param.isSecret || param.interactsWithSecret || scope.getReferencedIndicator(param).interactsWithSecret) { + if (param.isPrivate || param.isSecret || param.interactsWithSecret || scope.getReferencedIndicator(oldParam)?.interactsWithSecret) { if (param.typeName.isStruct) { param.typeName.properties.forEach((prop: any) => { newNodes.generateProofNode.parameters.push(`${param.name}.${prop.name}${param.typeName.isConstantArray ? '.all' : ''}`); diff --git a/src/traverse/NodePath.ts b/src/traverse/NodePath.ts index d6965f83..2b87ee8d 100644 --- a/src/traverse/NodePath.ts +++ b/src/traverse/NodePath.ts @@ -984,10 +984,21 @@ export default class NodePath { isConstantArray(node: any = this.node): boolean { if (!this.isArray(node)) return false; let arrLen; + console.log('vvvvvvvvvvvvvvvvvNodenode', node); switch (node.nodeType) { case 'IndexAccess': arrLen = node.baseExpression.typeDescriptions.typeString.match(/(?<=\[)(\d+)(?=\])/); break; + + // case 'VariableDeclaration': + + // if (node.typeDescriptions && node.typeDescriptions.typeString) { + // arrLen = node.typeDescriptions.typeString.match(/(?<=\[)(\d+)(?=\])/); + // } else if (node.typeName && typeof node.typeName.name === 'string' && !isNaN(node.typeName.name)) { + // return false; + // } + // break; + case 'Identifier': default: arrLen = node.typeDescriptions.typeString.match(/(?<=\[)(\d+)(?=\])/); diff --git a/src/traverse/Scope.ts b/src/traverse/Scope.ts index 52b8e176..bac6b5ac 100644 --- a/src/traverse/Scope.ts +++ b/src/traverse/Scope.ts @@ -393,11 +393,17 @@ export class Scope { */ getReferencedIndicator(referencingNode: any, mappingKeyIndicatorOnly: boolean = false): StateVariableIndicator | MappingKey | null { const { path } = this; - if (!referencingNode) return null; + if (!referencingNode) + return null; + + //if (referencingNode.nodeType === 'VariableDeclaration') return null ; + + const indicator = this.getIndicatorById( - path.getReferencedDeclarationId(referencingNode) || referencingNode.id + path.getReferencedDeclarationId(referencingNode) || referencingNode?.id ); + if (!path.isMapping(referencingNode) && !path.isArray(referencingNode) && !path.isStruct(referencingNode)) return indicator; if (path.isStruct(referencingNode) && NodePath.getPath(referencingNode).getAncestorOfType('MemberAccess') && path.isMapping(referencingNode)) { @@ -407,39 +413,42 @@ export class Scope { .node; const indexAccessNode = - memberAccessNode.expression.nodeType === 'IndexAccess' + memberAccessNode.expression?.nodeType === 'IndexAccess' ? memberAccessNode.expression : NodePath.getPath(memberAccessNode).getAncestorOfType('IndexAccess') - .node; + ?.node; return mappingKeyIndicatorOnly ? indicator.mappingKeys[this.getMappingKeyName(indexAccessNode)] : indicator; } - if (path.isStruct(referencingNode) && NodePath.getPath(referencingNode).getAncestorOfType('MemberAccess')) { + if (path.isStruct(referencingNode) && NodePath.getPath(referencingNode)?.getAncestorOfType('MemberAccess')) { const memberAccessNode = referencingNode.nodeType === 'MemberAccess' ? referencingNode - : NodePath.getPath(referencingNode).getAncestorOfType('MemberAccess') + : NodePath.getPath(referencingNode)?.getAncestorOfType('MemberAccess') .node; return mappingKeyIndicatorOnly ? indicator.structProperties[memberAccessNode.memberName] : indicator; } + + //if (path.isConstantArray(referencingNode) && referencingNode.nodeType === 'variableDeclaration') return null; if ((path.isConstantArray(referencingNode) || referencingNode.memberName === 'length') && !NodePath.getPath(referencingNode).getAncestorOfType('IndexAccess')) return indicator; - + // getMappingKeyName requires an indexAccessNode - referencingNode may be a baseExpression or indexExpression contained Identifier const indexAccessNode = referencingNode.nodeType === 'IndexAccess' ? referencingNode - : NodePath.getPath(referencingNode).getAncestorOfType('IndexAccess') - .node; + : NodePath.getPath(referencingNode)?.getAncestorOfType('IndexAccess') + ?.node; return mappingKeyIndicatorOnly - ? indicator.mappingKeys[this.getMappingKeyName(indexAccessNode)] + ? indicator?.mappingKeys[this.getMappingKeyName(indexAccessNode)] : indicator; } + /** * @returns {Node || null} - the node (VariableDeclaration) being referred-to by the input referencingNode. diff --git a/test/contracts/Arrays-input.zol b/test/contracts/Arrays-input.zol index 4e4c9d15..3efb290c 100644 --- a/test/contracts/Arrays-input.zol +++ b/test/contracts/Arrays-input.zol @@ -10,7 +10,7 @@ contract Assign { function add(secret uint256[5] calldata value, uint256[5] calldata publicValue) public { b = publicValue; - for (uint256 index = 0; index < 6; index++) { + for (uint256 index = 0; index < 2; index++) { known a += value[index]; } } From 2c5a92c8bca8276d8eaed897b320f7e9174ea858 Mon Sep 17 00:00:00 2001 From: kkahina Date: Fri, 30 Aug 2024 16:51:16 +0100 Subject: [PATCH 22/25] fixe IndexAccess --- .../visitors/toOrchestrationVisitor.ts | 67 ++++--------------- src/traverse/NodePath.ts | 11 --- src/traverse/Scope.ts | 6 +- test/contracts/Arrays-input.zol | 2 +- 4 files changed, 14 insertions(+), 72 deletions(-) diff --git a/src/transformers/visitors/toOrchestrationVisitor.ts b/src/transformers/visitors/toOrchestrationVisitor.ts index aed1d936..0c0ede52 100644 --- a/src/transformers/visitors/toOrchestrationVisitor.ts +++ b/src/transformers/visitors/toOrchestrationVisitor.ts @@ -298,7 +298,7 @@ if (name.endsWith('_')) { expression: InnerNode, interactsWithSecret: true, }); - + if (location.trueIndex !== -1){ fnDefNode.node._newASTPointer.body.preStatements[ifPreIndex].trueBody.push(newNode1); } else if (location.falseIndex !== -1){ fnDefNode.node._newASTPointer.body.preStatements[ifPreIndex].falseBody.push(newNode1); } else {fnDefNode.node._newASTPointer.body.preStatements.push(newNode1);} @@ -343,6 +343,7 @@ if (name.endsWith('_')) { } } } + // After the non-secret variables have been modified we need to reset the original variable name to its initial value. @@ -1393,6 +1394,16 @@ const visitor = { leftHandSide, rightHandSide: binOpNode, }); + if (path.node.leftHandSide.nodeType === 'IndexAccess') { + binOpNode.leftExpression.name = path.node.leftHandSide.baseExpression.name+'_'+ path.node.leftHandSide.indexExpression.name; + + } else { + binOpNode.leftExpression.name = path.node.leftHandSide.name; + } + + + + return assNode; }; @@ -1419,60 +1430,6 @@ const visitor = { // node._newASTPointer = newNode; // no need to ascribe the node._newASTPointer, because we're exiting. }, }, - // Assignment: { - // enter(path: NodePath) { - // const { node, parent } = path; - // const newNode = buildNode(node.nodeType, { operator: node.operator }); - // node._newASTPointer = newNode; - - // if (parent._newASTPointer.nodeType === 'VariableDeclarationStatement') { - // parent._newASTPointer.initialValue = newNode; - // } else { - // parent._newASTPointer.expression = newNode; - // } - // }, - - // exit(path: NodePath) { - // // Convert 'a += b' into 'a = a + b' for all operators - // const expandAssignment = (node: any) => { - // const { operator, leftHandSide, rightHandSide } = node; - // const expandableOps = ['+=', '-=', '*=', '/=', '%=', '|=', '&=', '^=']; - // if (!expandableOps.includes(operator)) return node; - // const op = operator.charAt(0); - // const binOpNode = buildNode('BinaryOperation', { - // operator: op, - // leftExpression: cloneDeep(leftHandSide), - // rightExpression: rightHandSide, - // }); - // const assNode = buildNode('Assignment', { - // operator: '=', - // leftHandSide, - // rightHandSide: binOpNode, - // }); - // return assNode; - // }; - - // const { parent } = path; - // const binding = path.getReferencedBinding(path.node.leftHandSide); - // if (binding instanceof VariableBinding && !binding.isSecret && binding.stateVariable) { - // if (parent._newASTPointer.nodeType === 'VariableDeclarationStatement') { - // const circuitNode = parent._newASTPointer.initialValue; - // const newNode = expandAssignment(circuitNode); - // parent._newASTPointer.initialValue = newNode; - // } else { - // const circuitNode = parent._newASTPointer.expression; - // const newNode = expandAssignment(circuitNode); - // parent._newASTPointer.expression = newNode; - // } - // } - // if (path.getAncestorContainedWithin('initializationExpression') && parent._newASTPointer.nodeType === 'VariableDeclarationStatement') { - // parent._newASTPointer.initialValue.isInitializationAssignment = true; - // } else if (path.getAncestorContainedWithin('initializationExpression')) { - // parent._newASTPointer.expression.isInitializationAssignment = true; - // } - // }, - // }, - TupleExpression: { enter(path: NodePath, state: any) { diff --git a/src/traverse/NodePath.ts b/src/traverse/NodePath.ts index 2b87ee8d..d6965f83 100644 --- a/src/traverse/NodePath.ts +++ b/src/traverse/NodePath.ts @@ -984,21 +984,10 @@ export default class NodePath { isConstantArray(node: any = this.node): boolean { if (!this.isArray(node)) return false; let arrLen; - console.log('vvvvvvvvvvvvvvvvvNodenode', node); switch (node.nodeType) { case 'IndexAccess': arrLen = node.baseExpression.typeDescriptions.typeString.match(/(?<=\[)(\d+)(?=\])/); break; - - // case 'VariableDeclaration': - - // if (node.typeDescriptions && node.typeDescriptions.typeString) { - // arrLen = node.typeDescriptions.typeString.match(/(?<=\[)(\d+)(?=\])/); - // } else if (node.typeName && typeof node.typeName.name === 'string' && !isNaN(node.typeName.name)) { - // return false; - // } - // break; - case 'Identifier': default: arrLen = node.typeDescriptions.typeString.match(/(?<=\[)(\d+)(?=\])/); diff --git a/src/traverse/Scope.ts b/src/traverse/Scope.ts index bac6b5ac..92a7d9c7 100644 --- a/src/traverse/Scope.ts +++ b/src/traverse/Scope.ts @@ -396,14 +396,10 @@ export class Scope { if (!referencingNode) return null; - //if (referencingNode.nodeType === 'VariableDeclaration') return null ; - - const indicator = this.getIndicatorById( path.getReferencedDeclarationId(referencingNode) || referencingNode?.id ); - - + if (!path.isMapping(referencingNode) && !path.isArray(referencingNode) && !path.isStruct(referencingNode)) return indicator; if (path.isStruct(referencingNode) && NodePath.getPath(referencingNode).getAncestorOfType('MemberAccess') && path.isMapping(referencingNode)) { diff --git a/test/contracts/Arrays-input.zol b/test/contracts/Arrays-input.zol index 3efb290c..3a4d4209 100644 --- a/test/contracts/Arrays-input.zol +++ b/test/contracts/Arrays-input.zol @@ -10,7 +10,7 @@ contract Assign { function add(secret uint256[5] calldata value, uint256[5] calldata publicValue) public { b = publicValue; - for (uint256 index = 0; index < 2; index++) { + for (uint256 index = 0; index < 5; index++) { known a += value[index]; } } From 631d017626929bbffeabbe32a7c298267b982d9c Mon Sep 17 00:00:00 2001 From: kkahina Date: Fri, 30 Aug 2024 19:19:30 +0100 Subject: [PATCH 23/25] Remove space-Test done --- src/transformers/visitors/toOrchestrationVisitor.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/transformers/visitors/toOrchestrationVisitor.ts b/src/transformers/visitors/toOrchestrationVisitor.ts index 0c0ede52..b5d134ea 100644 --- a/src/transformers/visitors/toOrchestrationVisitor.ts +++ b/src/transformers/visitors/toOrchestrationVisitor.ts @@ -274,7 +274,6 @@ if (name.endsWith('_')) { - const newNode1 = buildNode('VariableDeclarationStatement', { declarations: [decInnerNode], initialValue: initInnerNode, @@ -1396,14 +1395,9 @@ const visitor = { }); if (path.node.leftHandSide.nodeType === 'IndexAccess') { binOpNode.leftExpression.name = path.node.leftHandSide.baseExpression.name+'_'+ path.node.leftHandSide.indexExpression.name; - } else { binOpNode.leftExpression.name = path.node.leftHandSide.name; } - - - - return assNode; }; From 009fe4898e4d770706d5aa17f5eecfa5f5ae1563 Mon Sep 17 00:00:00 2001 From: kkahina Date: Mon, 2 Sep 2024 14:06:59 +0100 Subject: [PATCH 24/25] fixe comments and correct contracts --- .../javascript/raw/toOrchestration.ts | 2 - .../orchestration/nodejs/toOrchestration.ts | 7 +--- .../checks/interactsWithSecretVisitor.ts | 4 +- .../visitors/toContractVisitor.ts | 1 - .../visitors/toOrchestrationVisitor.ts | 16 ++------ src/traverse/Scope.ts | 3 -- test/contracts/Arrays-input.zol | 2 +- test/contracts/Boolean-public.zol | 39 ------------------- test/contracts/Non-Secret-Array.zol | 8 ++++ 9 files changed, 15 insertions(+), 67 deletions(-) delete mode 100644 test/contracts/Boolean-public.zol diff --git a/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts b/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts index 03a9fd6d..c6e1e14e 100644 --- a/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts +++ b/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts @@ -168,8 +168,6 @@ export const generateProofBoilerplate = (node: any) => { !output.join().includes(`${para}.integer`) && !output.join().includes('msgValue')), ) - - ?.forEach((param: string) => { if (param == 'msgSender') { parameters.unshift(`\t${param}.integer,`); diff --git a/src/codeGenerators/orchestration/nodejs/toOrchestration.ts b/src/codeGenerators/orchestration/nodejs/toOrchestration.ts index aef4b9c3..ea3fe5f4 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.containsPublic || node.expression?.internalFunctionInteractsWithSecret)){ let privateStateName = node.privateStateName.replace(/\./g, '_'); let increments; @@ -174,17 +173,13 @@ export default function codeGenerator(node: any, options: any = {}): any { if (!node.isInitializationAssignment && node.rightHandSide.subType !== 'generalNumber'){ if (['+=', '-=', '*='].includes(node.operator)) { - return `${codeGenerator(node.leftHandSide, { lhs: true, })} = generalise(${codeGenerator(node.leftHandSide)} ${node.operator.charAt( 0, )} ${codeGenerator(node.rightHandSide)})`; - } - - - return `${codeGenerator(node.leftHandSide, { lhs: true })} ${ + return `${codeGenerator(node.leftHandSide, { lhs: true })} ${ node.operator } generalise(${codeGenerator(node.rightHandSide)})`; diff --git a/src/transformers/visitors/checks/interactsWithSecretVisitor.ts b/src/transformers/visitors/checks/interactsWithSecretVisitor.ts index 118b4b14..68e42518 100644 --- a/src/transformers/visitors/checks/interactsWithSecretVisitor.ts +++ b/src/transformers/visitors/checks/interactsWithSecretVisitor.ts @@ -44,7 +44,7 @@ const markIndicatorSubtreeInteractsWithSecret = (thisPath: any, thisState: any) indicator.addSecretInteractingPath(thisState.secretPath); }; -const interactwithPublicSecret = (thisPath: any, thisState: any) => { +const interactwithInferSecret = (thisPath: any, thisState: any) => { const { node, scope } = thisPath; if (node.nodeType === 'ExpressionStatement') { const leftHandSideIndicator = scope.getReferencedIndicator(node.expression.leftHandSide, true); @@ -76,7 +76,7 @@ export default { FunctionDefinition: { exit(path: NodePath) { - path.traversePathsFast(interactwithPublicSecret, { + path.traversePathsFast(interactwithInferSecret, { publicPath: path, }); }, diff --git a/src/transformers/visitors/toContractVisitor.ts b/src/transformers/visitors/toContractVisitor.ts index c43fc69e..6e740950 100644 --- a/src/transformers/visitors/toContractVisitor.ts +++ b/src/transformers/visitors/toContractVisitor.ts @@ -59,7 +59,6 @@ const findCustomInputsVisitor = (thisPath: NodePath, thisState: any) => { ) { thisState.customInputs ??= []; const type = binding.node.typeName.nodeType === 'Mapping' ? binding.node.typeName.valueType.name : binding.node.typeName.name; - const isConstantArray = thisPath.isConstantArray(); const arrayLength = isConstantArray && thisPath.node.typeName?.length ? thisPath.node.typeName.length.value : false; diff --git a/src/transformers/visitors/toOrchestrationVisitor.ts b/src/transformers/visitors/toOrchestrationVisitor.ts index b5d134ea..9f9dee3a 100644 --- a/src/transformers/visitors/toOrchestrationVisitor.ts +++ b/src/transformers/visitors/toOrchestrationVisitor.ts @@ -117,10 +117,8 @@ const addPublicInput = (path: NodePath, state: any, IDnode: any) => { const { node } = path; let { name } = path.scope.getReferencedIndicator(node, true) || path.node; -// if (name.includes('[') && name.includes(']')) { -// name = name.replace(/\[|\]/g, '_'); -// } -name = name.replace(/\[([^\]]+)\]/g, '_$1'); + + name = name.replace(/\[([^\]]+)\]/g, '_$1'); // Ensure there is no trailing underscore if (name.endsWith('_')) { @@ -172,9 +170,7 @@ if (name.endsWith('_')) { isAccessed: true, isSecret: false, }) - } - - else { + } else { innerNode = buildNode('VariableDeclaration', { name, isAccessed: true, @@ -331,7 +327,6 @@ if (name.endsWith('_')) { } }); - //We ensure here that the public variable used has the correct name, e.g index_2 instead of index. if(IDnode) { if (num_modifiers != 0) { @@ -343,8 +338,6 @@ if (name.endsWith('_')) { } } - - // After the non-secret variables have been modified we need to reset the original variable name to its initial value. // e.g. index = index_init. @@ -987,7 +980,6 @@ const visitor = { } // this adds other values we need in the circuit - for (const param of node._newASTPointer.parameters.parameters) { let oldParam : any ; for(const para of node.parameters.parameters) { @@ -995,7 +987,6 @@ const visitor = { oldParam = para ; break; } - if (param.isPrivate || param.isSecret || param.interactsWithSecret || scope.getReferencedIndicator(oldParam)?.interactsWithSecret) { if (param.typeName.isStruct) { param.typeName.properties.forEach((prop: any) => { @@ -1003,7 +994,6 @@ const visitor = { }); } else newNodes.generateProofNode.parameters.push(`${param.name}${param.typeName.isConstantArray ? '.all' : ''}`); } - } if (state.publicInputs) { state.publicInputs.forEach((input: any) => { diff --git a/src/traverse/Scope.ts b/src/traverse/Scope.ts index 92a7d9c7..dbc98ef0 100644 --- a/src/traverse/Scope.ts +++ b/src/traverse/Scope.ts @@ -429,8 +429,6 @@ export class Scope { : indicator; } - - //if (path.isConstantArray(referencingNode) && referencingNode.nodeType === 'variableDeclaration') return null; if ((path.isConstantArray(referencingNode) || referencingNode.memberName === 'length') && !NodePath.getPath(referencingNode).getAncestorOfType('IndexAccess')) return indicator; // getMappingKeyName requires an indexAccessNode - referencingNode may be a baseExpression or indexExpression contained Identifier @@ -445,7 +443,6 @@ export class Scope { : indicator; } - /** * @returns {Node || null} - the node (VariableDeclaration) being referred-to by the input referencingNode. */ diff --git a/test/contracts/Arrays-input.zol b/test/contracts/Arrays-input.zol index 3a4d4209..0bf6f7fe 100644 --- a/test/contracts/Arrays-input.zol +++ b/test/contracts/Arrays-input.zol @@ -5,7 +5,7 @@ pragma solidity ^0.8.0; contract Assign { secret uint256 private a; - uint256[6] public b; + uint256[5] public b; function add(secret uint256[5] calldata value, uint256[5] calldata publicValue) public { diff --git a/test/contracts/Boolean-public.zol b/test/contracts/Boolean-public.zol deleted file mode 100644 index 7348e9a7..00000000 --- a/test/contracts/Boolean-public.zol +++ /dev/null @@ -1,39 +0,0 @@ -// SPDX-License-Identifier: CC0 - -pragma solidity ^0.8.0; - -contract Assign { - - secret bool private a; - secret bool private c; - bool public d; - bool public g; - - - function add( secret uint256 value, secret bool value_bool, bool value_publicbool) public { - secret bool l = true; - bool m = false; - c = a && m && d; - if(value > 10 && !c) { - c=true; - a= value_bool && value_publicbool; - } - if( value < 10) { - a =!c; - c= l || a || m; - } - } - - function addPublic(uint256 value, bool value_publicbool) public { - if (value > 10) { - d = true; - g = value_publicbool; - } - if (value < 10) { - d = false; - g = !value_publicbool; - } - } - - -} diff --git a/test/contracts/Non-Secret-Array.zol b/test/contracts/Non-Secret-Array.zol index 0bf83af6..2df97865 100644 --- a/test/contracts/Non-Secret-Array.zol +++ b/test/contracts/Non-Secret-Array.zol @@ -8,10 +8,18 @@ uint256 public index; uint256[3] public c; +function add( uint256 value) public { +c[index] += value; +} function add1( uint256 value) public { c[index] += value; known a += c[index]; } +function add2( uint256 value) public { +c[index] += value; +known a += value; +} + } \ No newline at end of file From 523bb1c841fdb34ce33d9e179b752507b0d56c82 Mon Sep 17 00:00:00 2001 From: kkahina Date: Mon, 2 Sep 2024 16:29:54 +0100 Subject: [PATCH 25/25] change to inferInteractsWithSecret --- .../javascript/raw/toOrchestration.ts | 31 ++---------- .../orchestration/nodejs/toOrchestration.ts | 43 ++++++---------- .../checks/interactsWithSecretVisitor.ts | 6 +-- .../visitors/toOrchestrationVisitor.ts | 50 +------------------ src/traverse/Scope.ts | 11 ---- 5 files changed, 22 insertions(+), 119 deletions(-) diff --git a/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts b/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts index c6e1e14e..0c68387c 100644 --- a/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts +++ b/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts @@ -109,7 +109,6 @@ export const sendTransactionBoilerplate = (node: any) => { output[5].push(`${privateStateName}_cipherText`); output[6].push(`${privateStateName}_encKey`); } - break; } } @@ -139,7 +138,6 @@ export const generateProofBoilerplate = (node: any) => { // we include the state variable key (mapping key) if its not a param (we include params separately) const msgSenderParamAndMappingKey = stateNode.isMapping && (node.parameters.includes('msgSender') || output.join().includes('_msg_stateVarId_key.integer')) && stateNode.stateVarId[1] === 'msg'; const msgValueParamAndMappingKey = stateNode.isMapping && (node.parameters.includes('msgValue') || output.join().includes('_msg_stateVarId_key.integer')) && stateNode.stateVarId[1] === 'msg'; - const constantMappingKey = stateNode.isMapping && (+stateNode.stateVarId[1] || stateNode.stateVarId[1] === '0'); // We are keeping this code in comments, for future if have any issue with extra mapping keys getting added for a zapp we can come to this @@ -161,13 +159,11 @@ export const generateProofBoilerplate = (node: any) => { : []; // we add any extra params the circuit needs node.parameters - .filter( (para: string) => !privateStateNames.includes(para) && ( !output.join().includes(`${para}.integer`) && !output.join().includes('msgValue')), ) - ?.forEach((param: string) => { if (param == 'msgSender') { parameters.unshift(`\t${param}.integer,`); @@ -178,7 +174,6 @@ export const generateProofBoilerplate = (node: any) => { else { parameters.push(`\t${param}.integer,`); } - }); // then we build boilerplate code per state @@ -241,7 +236,6 @@ export const generateProofBoilerplate = (node: any) => { isSharedSecret: stateNode.isSharedSecret, parameters, }) - ); containsNullifierRoot = true; containsNewNullifierRoot = true; @@ -325,7 +319,6 @@ export const preimageBoilerPlate = (node: any) => { accessedOnly: true, stateVarIds, })); - continue; } @@ -507,21 +500,18 @@ export const OrchestrationCodeBoilerPlate: any = (node: any) => { lines.push(`\nconst ${param} = generalise(_${param});`); params.push(`_${param}`); }); - node.parameters.modifiedStateVariables.forEach((param: any) => { states.push(`_${param.name}_newOwnerPublicKey = 0`); lines.push( `\nlet ${param.name}_newOwnerPublicKey = generalise(_${param.name}_newOwnerPublicKey);`, ); }); - if (node.decrementsSecretState) { node.decrementedSecretStates.forEach((decrementedState: string) => { states.push(` _${decrementedState}_0_oldCommitment = 0`); states.push(` _${decrementedState}_1_oldCommitment = 0`); }); } - node.returnParameters.forEach( (param, index) => { if(param === 'true') rtnparams?.push('bool: bool'); @@ -529,7 +519,6 @@ export const OrchestrationCodeBoilerPlate: any = (node: any) => { rtnparams?.push( ` ${param.replace('_change', '')}_newCommitmentValue : ${param}.integer `); }); if (params) params[params.length - 1] += `,`; - if (node.name === 'cnstrctr') return { signature: [ @@ -551,7 +540,6 @@ export const OrchestrationCodeBoilerPlate: any = (node: any) => { statements: lines, }; } - if(rtnparams.includes('bool: bool')) { return { signature: [ @@ -564,7 +552,6 @@ export const OrchestrationCodeBoilerPlate: any = (node: any) => { statements: lines, }; } - return { signature: [ ` ${functionSig} @@ -607,7 +594,6 @@ export const OrchestrationCodeBoilerPlate: any = (node: any) => { mappingName: stateNode.mappingName || stateName, structProperties: stateNode.structProperties })); - } return { statements: lines, @@ -753,7 +739,7 @@ export const OrchestrationCodeBoilerPlate: any = (node: any) => { statements: [`\n// Extract set membership witness: \n\n`, ...lines], }; - case 'CalculateNullifier': + case 'CalculateNullifier': for ([stateName, stateNode] of Object.entries(node.privateStates)) { if (stateNode.isPartitioned) { lines.push( @@ -763,7 +749,6 @@ export const OrchestrationCodeBoilerPlate: any = (node: any) => { accessedOnly: stateNode.accessedOnly, stateType: 'partitioned', })); - } else { lines.push( Orchestrationbp.calculateNullifier.postStatements({ @@ -774,7 +759,6 @@ export const OrchestrationCodeBoilerPlate: any = (node: any) => { })); } } - for ([stateName, stateNode] of Object.entries(node.privateStates)) { if (stateNode.isPartitioned) { lines.push( @@ -783,7 +767,6 @@ export const OrchestrationCodeBoilerPlate: any = (node: any) => { accessedOnly: stateNode.accessedOnly, stateType: 'partitioned', })); - } else { lines.push( Orchestrationbp.temporaryUpdatedNullifier.postStatements({ @@ -793,7 +776,6 @@ export const OrchestrationCodeBoilerPlate: any = (node: any) => { })); } } - for ([stateName, stateNode] of Object.entries(node.privateStates)) { if (stateNode.isPartitioned) { lines.push( @@ -812,7 +794,6 @@ export const OrchestrationCodeBoilerPlate: any = (node: any) => { })); } } - return { statements: [`\n// Calculate nullifier(s): \n`, ...lines], }; @@ -829,7 +810,6 @@ export const OrchestrationCodeBoilerPlate: any = (node: any) => { isSharedSecret: stateNode.isSharedSecret, structProperties: stateNode.structProperties, })); - break; case true: default: @@ -843,7 +823,6 @@ export const OrchestrationCodeBoilerPlate: any = (node: any) => { isSharedSecret: stateNode.isSharedSecret, structProperties: stateNode.structProperties, })); - break; case false: default: @@ -855,7 +834,6 @@ export const OrchestrationCodeBoilerPlate: any = (node: any) => { isSharedSecret: stateNode.isSharedSecret, structProperties: stateNode.structProperties, })); - } } } @@ -878,7 +856,7 @@ export const OrchestrationCodeBoilerPlate: any = (node: any) => { ], }; - case 'EncryptBackupPreimage': + case 'EncryptBackupPreimage': lines.push(`let BackupData = [];\n`) for ([stateName, stateNode] of Object.entries(node.privateStates)) { let stateType; @@ -953,8 +931,6 @@ export const OrchestrationCodeBoilerPlate: any = (node: any) => { ] } - - return { statements: [ `\n\n// Send transaction to the blockchain: @@ -997,8 +973,7 @@ export const OrchestrationCodeBoilerPlate: any = (node: any) => { ], }; - - case 'SendPublicTransaction': + case 'SendPublicTransaction': if (node.publicInputs[0]) { node.publicInputs.forEach((input: any) => { if (input.properties) { diff --git a/src/codeGenerators/orchestration/nodejs/toOrchestration.ts b/src/codeGenerators/orchestration/nodejs/toOrchestration.ts index ea3fe5f4..b0dce722 100644 --- a/src/codeGenerators/orchestration/nodejs/toOrchestration.ts +++ b/src/codeGenerators/orchestration/nodejs/toOrchestration.ts @@ -63,7 +63,6 @@ export default function codeGenerator(node: any, options: any = {}): any { const fn = OrchestrationCodeBoilerPlate(node); const statements = codeGenerator(node.body); fn.statements.push(statements); - return `${fn.signature[0]}\n\t${fn.statements.join('')}\n${ fn.signature[1] }`; @@ -96,7 +95,6 @@ export default function codeGenerator(node: any, options: any = {}): any { } else if (node.declarations[0].isAccessed) { return `${getAccessedValue(node.declarations[0].name)}`; } - if (!node.initialValue && !node.declarations[0].isAccessed) return `\nlet ${codeGenerator(node.declarations[0])};`; if (node.initialValue && node.initialValue.operator && @@ -111,17 +109,17 @@ export default function codeGenerator(node: any, options: any = {}): any { if (node.initialValue.nodeType === 'Literal' && node.isInitializationExpression) return `\nlet ${codeGenerator(node.declarations[0])} = ${codeGenerator(node.initialValue)};`; return `\nlet ${codeGenerator(node.declarations[0])} = generalise(${codeGenerator(node.initialValue)});`; } - return `\nlet ${codeGenerator(node.initialValue)};`; + return `\nlet ${codeGenerator(node.initialValue)};`; } case 'ElementaryTypeName': return; - case 'Block': { - const preStatements: string = (node.preStatements.flatMap(codeGenerator)); - const statements:string = (node.statements.flatMap(codeGenerator)); - const postStatements: string = (node.postStatements.flatMap(codeGenerator)); - return [...preStatements, ...statements, ...postStatements].join('\n\n'); + case 'Block': { + const preStatements: string = (node.preStatements.flatMap(codeGenerator)); + const statements:string = (node.statements.flatMap(codeGenerator)); + const postStatements: string = (node.postStatements.flatMap(codeGenerator)); + return [...preStatements, ...statements, ...postStatements].join('\n\n'); } case 'ExpressionStatement': @@ -131,15 +129,12 @@ export default function codeGenerator(node: any, options: any = {}): any { if (node.incrementsSecretState && (node.interactsWithSecret ||node.containsPublic || node.expression?.internalFunctionInteractsWithSecret)){ let privateStateName = node.privateStateName.replace(/\./g, '_'); let increments; - if (node.expression.operator === '+='){ 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_inc = generalise(parseInt(${privateStateName}_newCommitmentValue_inc.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`; @@ -160,17 +155,15 @@ export default function codeGenerator(node: any, options: any = {}): any { } } } - 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`; + return `\n// non-secret line would go here but has been filtered out`; + return `\n// increment would go here but has been filtered out`; case 'InternalFunctionCall': return " "; case 'Assignment': // To ensure the left hand side is always a general number, we generalise it here (excluding the initialisation in a for loop). - if (!node.isInitializationAssignment && node.rightHandSide.subType !== 'generalNumber'){ if (['+=', '-=', '*='].includes(node.operator)) { return `${codeGenerator(node.leftHandSide, { @@ -182,7 +175,6 @@ export default function codeGenerator(node: any, options: any = {}): any { return `${codeGenerator(node.leftHandSide, { lhs: true })} ${ node.operator } generalise(${codeGenerator(node.rightHandSide)})`; - } else { if (['+=', '-=', '*='].includes(node.operator)) { return `${codeGenerator(node.leftHandSide, { @@ -194,10 +186,8 @@ export default function codeGenerator(node: any, options: any = {}): any { return `${codeGenerator(node.leftHandSide, { lhs: true })} ${ node.operator } ${codeGenerator(node.rightHandSide)}`; - } - case 'BinaryOperation': return `${codeGenerator(node.leftExpression, { lhs: options.condition })} ${ node.operator @@ -208,9 +198,8 @@ export default function codeGenerator(node: any, options: any = {}): any { return `(${node.components.map(codeGenerator).join(` `)})`; return ` `; - case 'IfStatement': { + case 'IfStatement': { let comment = (node.inPreStatements) ? "// some public statements of this if statement have been moved to pre-statements here, any other statements appear later" : ''; - // We need to declare some variables before the if statement begins (because they are used outside the if statement). let preIfStatements = node.trueBody.filter((node: any) => node.outsideIf).concat(node.falseBody.filter((node: any) => node.outsideIf)); let newPreIfStatements = []; @@ -219,7 +208,6 @@ export default function codeGenerator(node: any, options: any = {}): any { newPreIfStatements[newPreIfStatements.length - 1].outsideIf = false; }); let preIfStatementsString = newPreIfStatements.flatMap(codeGenerator).join('\n'); - if(node.falseBody.length) return `${comment} ${preIfStatementsString} @@ -236,12 +224,12 @@ export default function codeGenerator(node: any, options: any = {}): any { }` } - case 'Conditional': { - return ` ${codeGenerator(node.condition)} ? - ${node.trueExpression.flatMap(codeGenerator).join('\n')} : ${node.falseExpression.flatMap(codeGenerator).join('\n')}` + case 'Conditional': { + return ` ${codeGenerator(node.condition)} ? + ${node.trueExpression.flatMap(codeGenerator).join('\n')} : ${node.falseExpression.flatMap(codeGenerator).join('\n')}` } - case 'ForStatement': { + case 'ForStatement': { if(node.interactsWithSecret) { let initializationExpression = `${codeGenerator(node.initializationExpression).trim()}`; let condition = `${codeGenerator(node.condition, { condition: true })};`; @@ -249,9 +237,8 @@ export default function codeGenerator(node: any, options: any = {}): any { return `for( ${node.initializationExpression.nodeType === 'VariableDeclarationStatement' ? `` : `let`} ${initializationExpression} ${condition} ${loopExpression}) { ${codeGenerator(node.body)} }` - } - else - return ''; + } else + return ''; } case 'MsgSender': diff --git a/src/transformers/visitors/checks/interactsWithSecretVisitor.ts b/src/transformers/visitors/checks/interactsWithSecretVisitor.ts index 68e42518..d223686b 100644 --- a/src/transformers/visitors/checks/interactsWithSecretVisitor.ts +++ b/src/transformers/visitors/checks/interactsWithSecretVisitor.ts @@ -44,11 +44,10 @@ const markIndicatorSubtreeInteractsWithSecret = (thisPath: any, thisState: any) indicator.addSecretInteractingPath(thisState.secretPath); }; -const interactwithInferSecret = (thisPath: any, thisState: any) => { +const inferInteractsWithSecret = (thisPath: any, thisState: any) => { const { node, scope } = thisPath; if (node.nodeType === 'ExpressionStatement') { const leftHandSideIndicator = scope.getReferencedIndicator(node.expression.leftHandSide, true); - if (leftHandSideIndicator?.interactsWithSecret) { thisPath.traversePathsFast(markIndicatorSubtreeInteractsWithSecret, { secretPath: thisPath, @@ -66,7 +65,6 @@ export default { path.getAncestorOfType('ExpressionStatement') || path.parentPath; if (path.isExternalFunctionCall()) { path.markContainsPublic(); - // below ensures that the return value and args are marked as interactsWithPublic expressionPath.traversePathsFast(markSubtreeInteractsWithPublic, { publicPath: path, }); @@ -76,7 +74,7 @@ export default { FunctionDefinition: { exit(path: NodePath) { - path.traversePathsFast(interactwithInferSecret, { + path.traversePathsFast(inferInteractsWithSecret, { publicPath: path, }); }, diff --git a/src/transformers/visitors/toOrchestrationVisitor.ts b/src/transformers/visitors/toOrchestrationVisitor.ts index 9f9dee3a..76deb3d4 100644 --- a/src/transformers/visitors/toOrchestrationVisitor.ts +++ b/src/transformers/visitors/toOrchestrationVisitor.ts @@ -340,9 +340,7 @@ if (name.endsWith('_')) { // After the non-secret variables have been modified we need to reset the original variable name to its initial value. // e.g. index = index_init. - fnDefNode.node._newASTPointer.body.preStatements = fnDefNode.node._newASTPointer.body.preStatements.filter(p => p.expression?.rightHandSide?.name !== `${node.name}_init`); - const endNodeInit = buildNode('Assignment', { leftHandSide: buildNode('Identifier', { name: `${node.name}`, subType: 'generalNumber' }), operator: '=', @@ -352,14 +350,12 @@ if (name.endsWith('_')) { expression: endNodeInit, interactsWithSecret: true, }); - fnDefNode.node._newASTPointer.body.preStatements.push(endNode); // if the node is the indexExpression, we dont need its value in the circuit state.publicInputs ??= []; if (!(path.containerName === 'indexExpression' && !(path.parentPath.isSecret|| path.parent.containsSecret))) state.publicInputs.push(node); } - if (['Identifier', 'IndexAccess'].includes(node.indexExpression?.nodeType)) addPublicInput(NodePath.getPath(node.indexExpression), state, null); } /** @@ -375,7 +371,6 @@ const visitor = { enter(path: NodePath, state: any) { const { node, parent, scope } = path; node._newASTPointer = parent._newASTPointer; - const contractName = `${node.name}Shield`; if (scope.indicators.zkSnarkVerificationRequired) { const newNode = buildNode('File', { @@ -390,7 +385,6 @@ const visitor = { }); node._newASTPointer.push(newNode); } - let newNode = buildNode('SetupCommonFilesBoilerplate', { contractName, contractImports: state.contractImports, @@ -441,8 +435,6 @@ const visitor = { }); node._newASTPointer.push(newNode); } - - if (scope.indicators.newCommitmentsRequired) { const newNode = buildNode('EditableCommitmentCommonFilesBoilerplate'); node._newASTPointer.push(newNode); @@ -460,7 +452,6 @@ const visitor = { file.functionNames.push('joinCommitments'); file.functionNames.push('splitCommitments'); } - } if (file.nodes?.[0].nodeType === 'IntegrationTestBoilerplate') { file.nodes[0].constructorParams = state.constructorParams; @@ -471,6 +462,7 @@ const visitor = { path.traverse(explode(internalCallVisitor), state); }, }, + ImportDirective: { enter(path: NodePath, state: any) { const { node } = path; @@ -481,11 +473,9 @@ const visitor = { }); // we assume all import statements come before all functions }, - }, FunctionDefinition: { - enter(path: NodePath, state: any) { const { node, parent, scope } = path; if (scope.modifiesSecretState()) { @@ -494,7 +484,6 @@ const visitor = { node.fileName = fnName; // After getting an appropriate Name , we build the node - const newNode = buildNode('File', { fileName: fnName, // the name of this function fileExtension: '.mjs', @@ -503,8 +492,6 @@ const visitor = { buildNode('FunctionDefinition', { name: node.name, contractName }), ], }); - - node._newASTPointer = newNode.nodes[1]; // eslint-disable-line prefer-destructuring parent._newASTPointer.push(newNode); for (const file of parent._newASTPointer) { @@ -539,7 +526,6 @@ const visitor = { state.skipSubNodes = true; return; } - const contractName = `${parent.name}Shield`; const fnName = path.getUniqueFunctionName(); node.fileName = fnName; @@ -602,8 +588,6 @@ const visitor = { node._newASTPointer.msgSenderParam ??= state.msgSenderParam; node._newASTPointer.msgValueParam ??= state.msgValueParam; - - if(node.containsPublic && !scope.modifiesSecretState()){ interface PublicParam { name: string; @@ -612,14 +596,10 @@ const visitor = { isBool?: boolean; isAddress?: boolean; } - const sendPublicTransactionNode = buildNode('SendPublicTransaction', { functionName: node.fileName, publicInputs: [], }); - - - node.parameters.parameters.forEach((para: { isSecret: any; typeName: { name: string; }; name: any; _newASTPointer: { typeName: { properties: any[]; }; }; }) => { if (!para.isSecret) { if (path.isStructDeclaration(para) || path.isConstantArray(para) || (para.typeName && para.typeName.name === 'bool') || (para.typeName && para.typeName.name === 'address')) { @@ -643,18 +623,14 @@ const visitor = { } }); - // Add publics parametres to sendTransactionNode node._newASTPointer.body.postStatements.push(sendPublicTransactionNode); - node.parameters.parameters.forEach(para => { node._newASTPointer.publicInputs ??= []; node._newASTPointer.publicInputs.push(para.name); }); - } - - + // By this point, we've added a corresponding FunctionDefinition node to the newAST, with the same nodes as the original Solidity function, with some renaming here and there, and stripping out unused data from the oldAST. const functionIndicator: FunctionDefinitionIndicator = scope.indicators; for(const [, indicators ] of Object.entries(functionIndicator)){ @@ -685,7 +661,6 @@ const visitor = { } } } - let thisIntegrationTestFunction: any = {}; let thisIntegrationApiServiceFunction: any = {}; for (const file of parent._newASTPointer) { @@ -704,10 +679,8 @@ const visitor = { if(scope.modifiesSecretState()){ file.functionNames.push(node.fileName); } - } } - thisIntegrationTestFunction.parameters = node._newASTPointer.parameters; thisIntegrationTestFunction.newCommitmentsRequired = functionIndicator.newCommitmentsRequired; @@ -739,7 +712,6 @@ const visitor = { newNodes.generateProofNode.parameters.push(`msgValue`); delete state.msgValueParam; // reset } - const allIndicators: (StateVariableIndicator | MappingKey)[] = []; let stateVarIndicator: StateVariableIndicator | MappingKey; for ([, stateVarIndicator] of Object.entries( @@ -891,7 +863,6 @@ const visitor = { } if (secretModified || accessedOnly) { - newNodes.sendTransactionNode.privateStates[ name ] = buildPrivateStateNode('SendTransaction', { @@ -938,13 +909,10 @@ const visitor = { }); } } - - if (node.kind === 'constructor') { newNodes.writePreimageNode.isConstructor = true; newNodes.membershipWitnessNode.isConstructor = true; } - const newFunctionDefinitionNode = node._newASTPointer; // In If Statements we might have non-secret statements editing variables that later interact with a secret variable. @@ -1020,7 +988,6 @@ const visitor = { // this adds the return parameters which are marked as secret in the tx let returnPara = node._newASTPointer.returnParameters.parameters.filter((paramnode: any) => (paramnode.isSecret || paramnode.typeName.name === 'bool')).map(paramnode => (paramnode.name)) || []; - let returnIsSecret: string[] = []; const decStates = node._newASTPointer.decrementedSecretStates; if( node._newASTPointer.returnParameters.parameters) { @@ -1329,7 +1296,6 @@ const visitor = { node._newASTPointer = newNode.statements; parent._newASTPointer.body = newNode; }, - }, VariableDeclarationStatement: { @@ -1340,7 +1306,6 @@ const visitor = { node._newASTPointer = newNode; path.inList ? parent._newASTPointer.push(newNode) : parent._newASTPointer[path.containerName] = newNode; }, - }, BinaryOperation: { @@ -1350,7 +1315,6 @@ const visitor = { node._newASTPointer = newNode; path.inList ? parent._newASTPointer.push(newNode) : parent._newASTPointer[path.containerName] = newNode; }, - }, Assignment: { @@ -1405,7 +1369,6 @@ const visitor = { parent._newASTPointer.expression = newNode; } } - if (path.getAncestorContainedWithin('initializationExpression') && parent._newASTPointer.nodeType === 'VariableDeclarationStatement' ){ parent._newASTPointer.initialValue.isInitializationAssignment = true; } else if (path.getAncestorContainedWithin('initializationExpression')) { @@ -1426,7 +1389,6 @@ const visitor = { node._newASTPointer = newNode.components; parent._newASTPointer[path.containerName] = newNode; } - }, }, @@ -1553,7 +1515,6 @@ const visitor = { const accessedBeforeModification = indicator.isAccessed && indicator.accessedPaths[0].node.id < lhs.id && !indicator.accessedPaths[0].isModification(); if (accessedBeforeModification || path.isInSubScope()) accessed = true; - const newNode = buildNode('VariableDeclarationStatement', { oldASTId: node.id, declarations: [ @@ -1621,7 +1582,6 @@ const visitor = { exit(path: NodePath, state: any) { const { node, scope } = path; - const { leftHandSide: lhs } = node.expression; const indicator = scope.getReferencedIndicator(lhs, true); let name = indicator?.isMapping @@ -1699,7 +1659,6 @@ const visitor = { // we now have a param or a local var dec let interactsWithSecret = false; - scope.bindings[node.id].referencingPaths.forEach(refPath => { interactsWithSecret ||= refPath.node.interactsWithSecret; // check for internal function call if the parameter passed in the function call interacts with secret or not @@ -1768,7 +1727,6 @@ const visitor = { }); const dec = path.getAncestorOfType('VariableDeclaration').node; if (node.length.value && (path.isLocalStackVariable(dec) || path.isFunctionParameter(dec))) newNode.isConstantArray = true; - node._newASTPointer = newNode; if (Array.isArray(parent._newASTPointer)) { parent._newASTPointer.push(newNode); @@ -1785,10 +1743,8 @@ const visitor = { if(!!path.getAncestorOfType('EventDefinition')) return; if(!!path.getAncestorOfType('EmitStatement')) return; const newNode = buildNode(node.nodeType, { name: node.name }); - parent._newASTPointer[path.containerName] = newNode; }, - }, UserDefinedTypeName: { @@ -1855,8 +1811,6 @@ const visitor = { name, subType: node.typeDescriptions.typeString, }); - - // if this is a public state variable, this fn will add a public input addPublicInput(path, state, newNode); state.skipSubNodes = true; // the subnodes are baseExpression and indexExpression - we skip them diff --git a/src/traverse/Scope.ts b/src/traverse/Scope.ts index dbc98ef0..03486be5 100644 --- a/src/traverse/Scope.ts +++ b/src/traverse/Scope.ts @@ -341,7 +341,6 @@ export class Scope { if (scope.scopeType === scopeType) return true; scope = scope.parentScope; } - return false; } @@ -361,7 +360,6 @@ export class Scope { const id = this.path.getReferencedDeclarationId(node); if (!id) return null; // if the node doesn't refer to another variable return this.queryAncestors((s: Scope) => { - const binding = s.bindings[id] if (!mappingKeyIndicatorOnly) return binding; if (binding instanceof VariableBinding) return binding.mappingKeys[this.getMappingKeyName(referencingNode)]; @@ -395,30 +393,24 @@ export class Scope { const { path } = this; if (!referencingNode) return null; - const indicator = this.getIndicatorById( path.getReferencedDeclarationId(referencingNode) || referencingNode?.id ); - if (!path.isMapping(referencingNode) && !path.isArray(referencingNode) && !path.isStruct(referencingNode)) return indicator; - if (path.isStruct(referencingNode) && NodePath.getPath(referencingNode).getAncestorOfType('MemberAccess') && path.isMapping(referencingNode)) { const memberAccessNode = referencingNode.nodeType === 'MemberAccess' ? referencingNode : NodePath.getPath(referencingNode).getAncestorOfType('MemberAccess') .node; - const indexAccessNode = memberAccessNode.expression?.nodeType === 'IndexAccess' ? memberAccessNode.expression : NodePath.getPath(memberAccessNode).getAncestorOfType('IndexAccess') ?.node; - return mappingKeyIndicatorOnly ? indicator.mappingKeys[this.getMappingKeyName(indexAccessNode)] : indicator; } - if (path.isStruct(referencingNode) && NodePath.getPath(referencingNode)?.getAncestorOfType('MemberAccess')) { const memberAccessNode = referencingNode.nodeType === 'MemberAccess' ? referencingNode @@ -428,16 +420,13 @@ export class Scope { ? indicator.structProperties[memberAccessNode.memberName] : indicator; } - if ((path.isConstantArray(referencingNode) || referencingNode.memberName === 'length') && !NodePath.getPath(referencingNode).getAncestorOfType('IndexAccess')) return indicator; - // getMappingKeyName requires an indexAccessNode - referencingNode may be a baseExpression or indexExpression contained Identifier const indexAccessNode = referencingNode.nodeType === 'IndexAccess' ? referencingNode : NodePath.getPath(referencingNode)?.getAncestorOfType('IndexAccess') ?.node; - return mappingKeyIndicatorOnly ? indicator?.mappingKeys[this.getMappingKeyName(indexAccessNode)] : indicator;