From 0167e91604c0f0bd61e401f30ccfeb137878ff00 Mon Sep 17 00:00:00 2001 From: Lydia Garms Date: Wed, 10 Jul 2024 13:49:28 +0100 Subject: [PATCH 1/5] fix: condition in circuit for revert function needs to be negated and allow for error messages to be displayed --- .../circuit/zokrates/toCircuit.ts | 2 +- .../orchestration/nodejs/toOrchestration.ts | 10 ++++++ .../visitors/toOrchestrationVisitor.ts | 9 ++++++ src/types/orchestration-types.ts | 7 ++++ test/contracts/revert.zol | 32 +++++++++++++++++-- 5 files changed, 56 insertions(+), 4 deletions(-) diff --git a/src/codeGenerators/circuit/zokrates/toCircuit.ts b/src/codeGenerators/circuit/zokrates/toCircuit.ts index 8c92ee052..d040e3efa 100644 --- a/src/codeGenerators/circuit/zokrates/toCircuit.ts +++ b/src/codeGenerators/circuit/zokrates/toCircuit.ts @@ -251,7 +251,7 @@ function codeGenerator(node: any) { if(node.condition.leftExpression.nodeType == 'Identifier') node.condition.leftExpression.name = node.condition.leftExpression.name.replace('_temp',''); initialStatements+= ` - assert(${codeGenerator(node.condition)})`; + assert(!(${codeGenerator(node.condition)}))`; return initialStatements; } // we use our list of condition vars to init temp variables. diff --git a/src/codeGenerators/orchestration/nodejs/toOrchestration.ts b/src/codeGenerators/orchestration/nodejs/toOrchestration.ts index 305fa2f38..f780fe9fb 100644 --- a/src/codeGenerators/orchestration/nodejs/toOrchestration.ts +++ b/src/codeGenerators/orchestration/nodejs/toOrchestration.ts @@ -252,6 +252,16 @@ export default function codeGenerator(node: any, options: any = {}): any { "Require statement not satisfied: ${node.message[0].value}" );}\n`; + case 'RevertStatement': + if (!node.message){ + return `throw new Error( + "Revert statement." + );\n`; + } + return `throw new Error( + "Reverted due to the following: ${node.message}" + );\n`; + case 'Folder': case 'File': case 'EditableCommitmentCommonFilesBoilerplate': diff --git a/src/transformers/visitors/toOrchestrationVisitor.ts b/src/transformers/visitors/toOrchestrationVisitor.ts index 6ef991565..697b135ee 100644 --- a/src/transformers/visitors/toOrchestrationVisitor.ts +++ b/src/transformers/visitors/toOrchestrationVisitor.ts @@ -1794,6 +1794,15 @@ const visitor = { state.skipSubNodes = true; return; } + if (node.expression?.name === 'revert') { + const newNode = buildNode('RevertStatement', { + }); + parent._newASTPointer[path.containerName] = newNode; + if (node.arguments[0]) newNode.message = node.arguments[0].value; + parent._newASTPointer.interactsWithSecret = path.getAncestorOfType('IfStatement').node._newASTPointer.interactsWithSecret; + state.skipSubNodes = true; + return; + } if (node.kind !== 'typeConversion') { state.skipSubNodes = true; return; diff --git a/src/types/orchestration-types.ts b/src/types/orchestration-types.ts index 18b74a0bc..3135bd5c1 100644 --- a/src/types/orchestration-types.ts +++ b/src/types/orchestration-types.ts @@ -266,6 +266,13 @@ export default function buildNode(nodeType: string, fields: any = {}): any { message: [], }; } + case 'RevertStatement': { + const {} = fields; + return { + nodeType, + message: [], + }; + } case 'InitialisePreimage': case 'InitialiseKeys': case 'ReadPreimage': diff --git a/test/contracts/revert.zol b/test/contracts/revert.zol index f46fd8d51..91275a074 100644 --- a/test/contracts/revert.zol +++ b/test/contracts/revert.zol @@ -6,17 +6,43 @@ contract MyContract { secret uint256 private a; secret address private admin; + address private pubAdmin; constructor() { admin = msg.sender; + pubAdmin = msg.sender; } - function setAdmin(secret address newAdmin) public { - if(msg.sender == admin) { - revert(" revert "); + function setSecretAdmin(secret address newAdmin) public { + if(msg.sender != admin) { + revert("the msg sender is not admin "); } admin = newAdmin; a+= 1; } + + function setSecretAdmin1(secret address newAdmin) public { + if(msg.sender != admin) { + revert(); + } + admin = newAdmin; + a+= 1; + } + + function setPublicAdmin(address newAdmin) public { + if(msg.sender != pubAdmin) { + revert("the msg sender is not admin "); + } + pubAdmin = newAdmin; + a+= 1; + } + + function setPublicAdmin1(address newAdmin) public { + if(msg.sender != pubAdmin) { + revert(); + } + pubAdmin = newAdmin; + a+= 1; + } } From 1dbae60bc87cf4631385887d1015ff9db47d44db Mon Sep 17 00:00:00 2001 From: Lydia Garms Date: Wed, 10 Jul 2024 14:51:07 +0100 Subject: [PATCH 2/5] fix: public input addresses in send transaction in correct format --- .../javascript/raw/toOrchestration.ts | 23 +++++++++++++++---- .../visitors/toOrchestrationVisitor.ts | 9 ++++++-- test/contracts/revert.zol | 7 ++++++ 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts b/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts index a982206e5..348b5d34a 100644 --- a/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts +++ b/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts @@ -890,6 +890,8 @@ export const OrchestrationCodeBoilerPlate: any = (node: any) => { lines.push(`${input.name}.all.integer`); } else if(input.isBool) { lines.push(`parseInt(${input.name}.integer, 10)`); + } else if(input.isAddress) { + lines.push(`${input.name}.hex(20)`); } else { lines.push(`${input}.integer`); @@ -976,13 +978,26 @@ export const OrchestrationCodeBoilerPlate: any = (node: any) => { case 'SendPublicTransaction': - node.publicInputsString = node.publicInputs.map(input => - (typeof input === 'object' && !Array.isArray(input)) ? JSON.stringify(input) : input - ).join(','); + if (node.publicInputs[0]) { + node.publicInputs.forEach((input: any) => { + if (input.properties) { + lines.push(`[${input.properties.map(p => p.type === 'bool' ? `(${input.name}${input.isConstantArray ? '.all' : ''}.${p.name}.integer === "1")` : `${input.name}${input.isConstantArray ? '.all' : ''}.${p.name}.integer`).join(',')}]`); + } else if (input.isConstantArray) { + lines.push(`${input.name}.all.integer`); + } else if(input.isBool) { + lines.push(`parseInt(${input.name}.integer, 10)`); + } else if(input.isAddress) { + lines.push(`${input.name}.hex(20)`); + } + else { + lines.push(`${input}.integer`); + } + }); + } return { statements: [ `\n\n// Send transaction to the blockchain: - \nconst txData = await instance.methods.${node.functionName}(${node.publicInputsString}).encodeABI(); + \nconst txData = await instance.methods.${node.functionName}(${lines}).encodeABI(); \nlet txParams = { from: config.web3.options.defaultAccount, to: contractAddr, diff --git a/src/transformers/visitors/toOrchestrationVisitor.ts b/src/transformers/visitors/toOrchestrationVisitor.ts index 697b135ee..21808f413 100644 --- a/src/transformers/visitors/toOrchestrationVisitor.ts +++ b/src/transformers/visitors/toOrchestrationVisitor.ts @@ -511,6 +511,7 @@ const visitor = { properties?: { name: string; type: string }[]; isConstantArray?: boolean; isBool?: boolean; + isAddress?: boolean; } const sendPublicTransactionNode = buildNode('SendPublicTransaction', { @@ -522,7 +523,7 @@ const visitor = { 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')) { + if (path.isStructDeclaration(para) || path.isConstantArray(para) || (para.typeName && para.typeName.name === 'bool') || (para.typeName && para.typeName.name === 'address')) { let newParam: PublicParam = { name: para.name }; if (path.isStructDeclaration(para)) { newParam.properties = para._newASTPointer.typeName.properties.map(p => ({ "name": p.name, "type": p.type })); @@ -532,6 +533,9 @@ const visitor = { } if (para.typeName?.name === 'bool') { newParam.isBool = true; + } + if (para.typeName?.name === 'address') { + newParam.isAddress = true; } sendPublicTransactionNode.publicInputs.push(newParam); } else { @@ -859,12 +863,13 @@ const visitor = { // this adds other values we need in the tx for (const param of node.parameters.parameters) { if (!param.isSecret) { - if (path.isStructDeclaration(param) || path.isConstantArray(param) ||( param.typeName && param.typeName.name === 'bool')) { + if (path.isStructDeclaration(param) || path.isConstantArray(param) ||( param.typeName && param.typeName.name === 'bool') || ( param.typeName && param.typeName.name === 'address')) { let newParam: any = {}; newParam.name = param.name; if (path.isStructDeclaration(param)) newParam.properties = param._newASTPointer.typeName.properties.map(p => ({"name" : p.name, "type" : p.type })); if (path.isConstantArray(param)) newParam.isConstantArray = true; if (param.typeName?.name === 'bool') newParam.isBool = true; + if (param.typeName?.name === 'address') newParam.isAddress = true; newNodes.sendTransactionNode.publicInputs.push(newParam); } else newNodes.sendTransactionNode.publicInputs.push(param.name); } diff --git a/test/contracts/revert.zol b/test/contracts/revert.zol index 91275a074..eb559f9aa 100644 --- a/test/contracts/revert.zol +++ b/test/contracts/revert.zol @@ -45,4 +45,11 @@ contract MyContract { pubAdmin = newAdmin; a+= 1; } + + function setPublicAdmin2(address newAdmin) public { + if(msg.sender != pubAdmin) { + revert(); + } + pubAdmin = newAdmin; + } } From c136ec9087ebfce510eedc7ce3cd70e7b870fea4 Mon Sep 17 00:00:00 2001 From: Lydia Garms Date: Wed, 10 Jul 2024 18:23:54 +0100 Subject: [PATCH 3/5] fix: remove public parameters from custom inputs in orchestration if they are not input to the circuit --- .../javascript/raw/toOrchestration.ts | 21 +++++++++++++++++-- .../visitors/toOrchestrationVisitor.ts | 5 +++-- test/contracts/revert.zol | 4 ++-- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts b/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts index 348b5d34a..c6878de08 100644 --- a/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts +++ b/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts @@ -894,11 +894,28 @@ export const OrchestrationCodeBoilerPlate: any = (node: any) => { lines.push(`${input.name}.hex(20)`); } else { - lines.push(`${input}.integer`); + lines.push(`${input.name}.integer`); } }); } - returnInputs = returnInputs.concat(lines); + if (node.publicInputs[0]) { + node.publicInputs.forEach((input: any) => { + if (input.inCircuit){ + if (input.properties) { + returnInputs.push(`[${input.properties.map(p => p.type === 'bool' ? `(${input.name}${input.isConstantArray ? '.all' : ''}.${p.name}.integer === "1")` : `${input.name}${input.isConstantArray ? '.all' : ''}.${p.name}.integer`).join(',')}]`); + } else if (input.isConstantArray) { + returnInputs.push(`${input.name}.all.integer`); + } else if(input.isBool) { + returnInputs.push(`parseInt(${input.name}.integer, 10)`); + } else if(input.isAddress) { + returnInputs.push(`${input.name}.hex(20)`); + } + else { + returnInputs.push(`${input.name}.integer`); + } + } + }); + } if(node.returnInputs[0]) { node.returnInputs.forEach((input: any) => { diff --git a/src/transformers/visitors/toOrchestrationVisitor.ts b/src/transformers/visitors/toOrchestrationVisitor.ts index 21808f413..cf47c6521 100644 --- a/src/transformers/visitors/toOrchestrationVisitor.ts +++ b/src/transformers/visitors/toOrchestrationVisitor.ts @@ -863,15 +863,16 @@ const visitor = { // this adds other values we need in the tx for (const param of node.parameters.parameters) { if (!param.isSecret) { - if (path.isStructDeclaration(param) || path.isConstantArray(param) ||( param.typeName && param.typeName.name === 'bool') || ( param.typeName && param.typeName.name === 'address')) { + //if (path.isStructDeclaration(param) || path.isConstantArray(param) ||( param.typeName && param.typeName.name === 'bool') || ( param.typeName && param.typeName.name === 'address')) { let newParam: any = {}; newParam.name = param.name; + if (param._newASTPointer.interactsWithSecret) newParam.inCircuit = true; if (path.isStructDeclaration(param)) newParam.properties = param._newASTPointer.typeName.properties.map(p => ({"name" : p.name, "type" : p.type })); if (path.isConstantArray(param)) newParam.isConstantArray = true; if (param.typeName?.name === 'bool') newParam.isBool = true; if (param.typeName?.name === 'address') newParam.isAddress = true; newNodes.sendTransactionNode.publicInputs.push(newParam); - } else newNodes.sendTransactionNode.publicInputs.push(param.name); + //} else newNodes.sendTransactionNode.publicInputs.push(param.name); } } // this adds the return parameters which are marked as secret in the tx diff --git a/test/contracts/revert.zol b/test/contracts/revert.zol index eb559f9aa..a84801eb4 100644 --- a/test/contracts/revert.zol +++ b/test/contracts/revert.zol @@ -14,12 +14,12 @@ contract MyContract { pubAdmin = msg.sender; } - function setSecretAdmin(secret address newAdmin) public { + function setSecretAdmin(secret address newAdmin, uint256 value) public { if(msg.sender != admin) { revert("the msg sender is not admin "); } admin = newAdmin; - a+= 1; + a+= value; } function setSecretAdmin1(secret address newAdmin) public { From cb83db9d15da4a87c3f385d54766286c49665588 Mon Sep 17 00:00:00 2001 From: Lydia Garms Date: Thu, 11 Jul 2024 11:07:08 +0100 Subject: [PATCH 4/5] fix: display revert message correctly when no revert input --- src/types/orchestration-types.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/types/orchestration-types.ts b/src/types/orchestration-types.ts index 3135bd5c1..88b4d72a4 100644 --- a/src/types/orchestration-types.ts +++ b/src/types/orchestration-types.ts @@ -270,7 +270,6 @@ export default function buildNode(nodeType: string, fields: any = {}): any { const {} = fields; return { nodeType, - message: [], }; } case 'InitialisePreimage': From c77a9e063953a9cd976b2f72cba5a34a687d37d8 Mon Sep 17 00:00:00 2001 From: Lydia Garms Date: Thu, 11 Jul 2024 16:26:15 +0100 Subject: [PATCH 5/5] remove public parameters from custom inputs in orchestration (because they are already input anyway) --- .../javascript/raw/toOrchestration.ts | 20 +------------------ .../visitors/toOrchestrationVisitor.ts | 5 ++--- 2 files changed, 3 insertions(+), 22 deletions(-) diff --git a/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts b/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts index c6878de08..59925a05f 100644 --- a/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts +++ b/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts @@ -894,28 +894,10 @@ export const OrchestrationCodeBoilerPlate: any = (node: any) => { lines.push(`${input.name}.hex(20)`); } else { - lines.push(`${input.name}.integer`); + lines.push(`${input}.integer`); } }); } - if (node.publicInputs[0]) { - node.publicInputs.forEach((input: any) => { - if (input.inCircuit){ - if (input.properties) { - returnInputs.push(`[${input.properties.map(p => p.type === 'bool' ? `(${input.name}${input.isConstantArray ? '.all' : ''}.${p.name}.integer === "1")` : `${input.name}${input.isConstantArray ? '.all' : ''}.${p.name}.integer`).join(',')}]`); - } else if (input.isConstantArray) { - returnInputs.push(`${input.name}.all.integer`); - } else if(input.isBool) { - returnInputs.push(`parseInt(${input.name}.integer, 10)`); - } else if(input.isAddress) { - returnInputs.push(`${input.name}.hex(20)`); - } - else { - returnInputs.push(`${input.name}.integer`); - } - } - }); - } if(node.returnInputs[0]) { node.returnInputs.forEach((input: any) => { diff --git a/src/transformers/visitors/toOrchestrationVisitor.ts b/src/transformers/visitors/toOrchestrationVisitor.ts index cf47c6521..21808f413 100644 --- a/src/transformers/visitors/toOrchestrationVisitor.ts +++ b/src/transformers/visitors/toOrchestrationVisitor.ts @@ -863,16 +863,15 @@ const visitor = { // this adds other values we need in the tx for (const param of node.parameters.parameters) { if (!param.isSecret) { - //if (path.isStructDeclaration(param) || path.isConstantArray(param) ||( param.typeName && param.typeName.name === 'bool') || ( param.typeName && param.typeName.name === 'address')) { + if (path.isStructDeclaration(param) || path.isConstantArray(param) ||( param.typeName && param.typeName.name === 'bool') || ( param.typeName && param.typeName.name === 'address')) { let newParam: any = {}; newParam.name = param.name; - if (param._newASTPointer.interactsWithSecret) newParam.inCircuit = true; if (path.isStructDeclaration(param)) newParam.properties = param._newASTPointer.typeName.properties.map(p => ({"name" : p.name, "type" : p.type })); if (path.isConstantArray(param)) newParam.isConstantArray = true; if (param.typeName?.name === 'bool') newParam.isBool = true; if (param.typeName?.name === 'address') newParam.isAddress = true; newNodes.sendTransactionNode.publicInputs.push(newParam); - //} else newNodes.sendTransactionNode.publicInputs.push(param.name); + } else newNodes.sendTransactionNode.publicInputs.push(param.name); } } // this adds the return parameters which are marked as secret in the tx