Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allow for mappings to structs in BackupDataRetriever #345

Merged
merged 7 commits into from
Nov 22, 2024
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see there are two consecutive if statements. Could you explain why this separation is necessary instead of combining them into a single if with multiple conditions?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previously the if statement was inside else because we didn't have both structs and mappings at the same time. Now we are supporting mappings to structs and so we want to increment varName by s even if mappingKey is true.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the clarification

Original file line number Diff line number Diff line change
Expand Up @@ -579,8 +579,8 @@ encryptBackupPreimage = {
} else{
plainText = `[BigInt(${saltName}.hex(32)), BigInt(${stateName}_stateVarId),
${valueName}]`;
if (structProperties) varName += ` s`;
}
if (structProperties) varName += ` s`;
if (stateType === 'increment') varName += ` u`;
return[`\n\n// Encrypt pre-image for state variable ${stateName} as a backup: \n
let ${stateName}_ephSecretKey = generalise(utils.randomHex(31)); \n
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ export const sendTransactionBoilerplate = (node: any) => {
output[0].push(`${privateStateName}_nullifier.integer`);
}
}
if (!stateNode.burnedOnly)
if (!stateNode.accessedOnly && !stateNode.burnedOnly)
output[2].push(`${privateStateName}_newCommitment.integer`);
if (stateNode.encryptionRequired) {
output[4].push(`${privateStateName}_cipherText`);
Expand Down
114 changes: 71 additions & 43 deletions src/codeGenerators/orchestration/files/toOrchestration.ts
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the new code properly handle the state variable indices and structure properties without causing any issues or inconsistencies in the logic ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes as far as I'm aware, can you see any problems?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’ll go ahead and approve it

Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,8 @@ const prepareBackupVariable = (node: any) => {
let isStruct = false;
if (varName.includes(" a")) {
isArray = true;
} else if (varName.includes(" s")) {
}
if (varName.includes(" s")) {
isStruct = true;
}
const plainText = decrypt(
Expand All @@ -617,6 +618,7 @@ const prepareBackupVariable = (node: any) => {
console.log("Decrypted pre-image of commitment for variable name: " + name + ": ");
let salt = generalise(plainText[0]);
console.log(\`\\tSalt: \${salt.integer}\`);
let count;
if (isArray){
console.log(\`\\tState variable StateVarId: \${plainText[2]}\`);
mappingKey = generalise(plainText[1]);
Expand All @@ -632,36 +634,47 @@ const prepareBackupVariable = (node: any) => {
);
stateVarId = reGenStateVarId;
console.log(\`Regenerated StateVarId: \${reGenStateVarId.bigInt}\`);
value = generalise(plainText[3]);
console.log(\`\\tValue: \${value.integer}\`);
count = 3;
} else {
stateVarId = generalise(plainText[1]);
console.log(\`\\tStateVarId: \${plainText[1]}\`);
if (isStruct){
value = {};`;

node.privateStates.forEach((stateVar: any) => {
if (stateVar.structProperties){
let propCount = 2;
count = 2;
}
if (isStruct){
value = {};`;
node.privateStates.forEach((stateVar: any) => {
if (stateVar.structProperties){
let propCount = 2;
if (stateVar.mappingKey){
propCount++;
genericApiServiceFile += `\nif (stateVarId.integer ===
generalise(utils.mimcHash(
[
BigInt(${stateVar.stateVarId[0]}),
generalise(plainText[1]).bigInt,
],
"ALT_BN_254"
)).integer) {`
} else {
genericApiServiceFile += `\nif (stateVarId.integer === '${stateVar.stateVarId}') {`
stateVar.structProperties.forEach((prop: any) => {
genericApiServiceFile += `value.${prop} = plainText[${propCount}];\n`;
propCount++;
});
genericApiServiceFile += `}\n`;
}
});

genericApiServiceFile += `console.log(\`\\tValue: \${value}\`);
} else {
value = generalise(plainText[2]);
console.log(\`\\tValue: \${value.integer}\`);
}
stateVar.structProperties.forEach((prop: any) => {
genericApiServiceFile += `value.${prop} = plainText[${propCount}];\n`;
propCount++;
});
genericApiServiceFile += `}\n`;
}
});
genericApiServiceFile += `console.log(\`\\tValue: \${value}\`);
} else {
value = generalise(plainText[count]);
console.log(\`\\tValue: \${value.integer}\`);
}
let newCommitment;
if (isStruct){
let hashInput = [BigInt(stateVarId.hex(32))];
for (let i = 2; i < plainText.length; i++) {
let start = isArray ? 3 : 2;
for (let i = start; i < plainText.length; i++) {
hashInput.push(BigInt(generalise(plainText[i]).hex(32)));
}
hashInput.push(BigInt(publicKey.hex(32)));
Expand Down Expand Up @@ -792,7 +805,8 @@ const prepareBackupDataRetriever = (node: any) => {
let isStruct = false;
if (varName.includes(" a")) {
isArray = true;
} else if (varName.includes(" s")) {
}
if (varName.includes(" s")) {
isStruct = true;
}
const plainText = decrypt(
Expand All @@ -809,6 +823,7 @@ const prepareBackupDataRetriever = (node: any) => {
console.log("Decrypted pre-image of commitment for variable name: " + name + ": ");
let salt = generalise(plainText[0]);
console.log(\`\\tSalt: \${salt.integer}\`);
let count;
if (isArray){
console.log(\`\\tState variable StateVarId: \${plainText[2]}\`);
mappingKey = generalise(plainText[1]);
Expand All @@ -824,36 +839,49 @@ const prepareBackupDataRetriever = (node: any) => {
);
stateVarId = reGenStateVarId;
console.log(\`Regenerated StateVarId: \${reGenStateVarId.bigInt}\`);
value = generalise(plainText[3]);
console.log(\`\\tValue: \${value.integer}\`);
count = 3;
} else {
stateVarId = generalise(plainText[1]);
console.log(\`\\tStateVarId: \${plainText[1]}\`);
if (isStruct){
value = {};`;
count = 2;
}
if (isStruct){
value = {};`;

node.privateStates.forEach((stateVar: any) => {
if (stateVar.structProperties){
let propCount = 2;
node.privateStates.forEach((stateVar: any) => {
if (stateVar.structProperties){
let propCount = 2;
if (stateVar.mappingKey){
propCount++;
genericApiServiceFile += `\nif (stateVarId.integer ===
generalise(utils.mimcHash(
[
BigInt(${stateVar.stateVarId[0]}),
generalise(plainText[1]).bigInt,
],
"ALT_BN_254"
)).integer) {`
} else{
genericApiServiceFile += `\nif (stateVarId.integer === '${stateVar.stateVarId}') {`
stateVar.structProperties.forEach((prop: any) => {
genericApiServiceFile += `value.${prop} = plainText[${propCount}];\n`;
propCount++;
});
genericApiServiceFile += `}\n`;
}
});

genericApiServiceFile += `console.log(\`\\tValue: \${value}\`);
} else {
value = generalise(plainText[2]);
console.log(\`\\tValue: \${value.integer}\`);
}
stateVar.structProperties.forEach((prop: any) => {
genericApiServiceFile += `value.${prop} = plainText[${propCount}];\n`;
propCount++;
});
genericApiServiceFile += `}\n`;
}
});

genericApiServiceFile += `console.log(\`\\tValue: \${value}\`);
} else {
value = generalise(plainText[count]);
console.log(\`\\tValue: \${value.integer}\`);
}
let newCommitment;
if (isStruct){
let hashInput = [BigInt(stateVarId.hex(32))];
for (let i = 2; i < plainText.length; i++) {
let start = isArray ? 3 : 2;
for (let i = start; i < plainText.length; i++) {
hashInput.push(BigInt(generalise(plainText[i]).hex(32)));
}
hashInput.push(BigInt(publicKey.hex(32)));
Expand Down
7 changes: 3 additions & 4 deletions src/transformers/visitors/toOrchestrationVisitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1511,13 +1511,13 @@ const visitor = {
}
i++;
});

// check whether this should be a VariableDeclaration
const firstEdit =
(firstInstanceOfNewName && indicator.interactsWithSecret) ||
(!indicator.isStruct && indicator.modifyingPaths[0]?.node.id === lhs?.id && indicator.isSecret && indicator.isWhole) ||
(indicator.isStruct && indicator instanceof MappingKey && indicator.container.modifyingPaths[0]?.node.id === lhs?.id && indicator.isSecret && indicator.isWhole);

// We want to check the indicator of the struct and not the struct property
(indicator.isStruct && indicator instanceof MappingKey && !indicator.isMapping && indicator.container.modifyingPaths[0]?.node.id === lhs?.id && indicator.isSecret && indicator.isWhole) ||
((indicator.isStruct && indicator.isMapping && indicator.modifyingPaths[0]?.node.id === lhs?.id && indicator.isSecret && indicator.isWhole));
// We should only replace the _first_ assignment to this node. Let's look at the scope's modifiedBindings for any prior modifications to this binding:
// if its secret and this is the first assigment, we add a vardec
if (
Expand All @@ -1531,7 +1531,6 @@ const visitor = {
)
accessed = true;
});

// we still need to initialise accessed states if they were accessed _before_ this modification
const accessedBeforeModification = indicator.isAccessed && indicator.accessedPaths[0].node.id < lhs.id && !indicator.accessedPaths[0].isModification();

Expand Down
34 changes: 34 additions & 0 deletions test/contracts/MappingtoStruct2.zol
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// SPDX-License-Identifier: CC0

pragma solidity ^0.8.0;
contract Assign {
secret uint256 private a;
address public immutable owner;

struct myStruct {
uint256 prop1;
uint256 prop2;
uint256 prop3;
}
secret mapping(uint256 => myStruct) private d;



function add(secret uint256 value) public {
secret uint256 index1 = 0;
secret uint256 index2 = 5;
d[index1].prop1 = value;
d[index1].prop2 = value +1;
d[index1].prop3 = value +2;
d[index2].prop1 = 5;
d[index2].prop2 = 1;
d[index2].prop3 = 1;

}






}
Loading