Skip to content

Commit

Permalink
Merge pull request #304 from EYBlockchain/lydia/KnownUnknown
Browse files Browse the repository at this point in the history
Lydia/known unknown
  • Loading branch information
SwatiEY authored Aug 5, 2024
2 parents 1f85e62 + eca8c2e commit 0743cea
Show file tree
Hide file tree
Showing 18 changed files with 458 additions and 194 deletions.
41 changes: 27 additions & 14 deletions src/boilerplate/circuit/zokrates/nodes/BoilerplateGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import MappingKey from '../../../../traverse/MappingKey.js';
const collectIncrements = (bpg: BoilerplateGenerator) => {
const stateVarIndicator = bpg.thisIndicator || bpg.indicators;
const incrementsArray: any[] = [];
let incrementsString = '';
let incrementsString: string[] = [];

if (stateVarIndicator.isStruct && (
stateVarIndicator instanceof StateVariableIndicator ||
Expand All @@ -27,14 +27,15 @@ const collectIncrements = (bpg: BoilerplateGenerator) => {
bpg.thisIndicator = stateVarIndicator;
} else {
structIncs.incrementsArray[sp] = [];
structIncs.incrementsString[sp] = '0';
structIncs.incrementsString[sp] = ['0'];
}
}
return structIncs;
}

// TODO sometimes decrements are added to .increments
// current fix - prevent duplicates
let counter =-1;
for (const inc of stateVarIndicator.increments) {
if (inc.nodeType === 'IndexAccess') {
const mappingKeyName = NodePath.getPath(inc).scope.getMappingKeyName(inc);
Expand All @@ -46,19 +47,23 @@ const collectIncrements = (bpg: BoilerplateGenerator) => {
if (inc.nodeType === 'MemberAccess') inc.name ??= `${inc.expression.name}.${inc.memberName}`;
if (!inc.name) inc.name = inc.value;
let modName = inc.modName ? inc.modName : inc.name;
if (incrementsArray.some(existingInc => inc.name === existingInc.name))
if (incrementsArray.some(existingInc => inc.name === existingInc.name && inc.id === existingInc.id))
continue;
incrementsArray.push({
name: inc.name,
precedingOperator: inc.precedingOperator,
});

if (inc === stateVarIndicator.increments[0]) {
incrementsString += `${modName}`;
if (counter !== inc.counter) {
incrementsString[inc.counter] = `${modName}`;
} else {
incrementsString += ` ${inc.precedingOperator} ${modName}`;
incrementsString[inc.counter] += ` ${inc.precedingOperator} ${modName}`;
}
counter = inc.counter;
}
let incCounter;
(counter === -1) ? incCounter = 0 : incCounter = counter +1;
counter = -1;
for (const dec of stateVarIndicator.decrements) {
if (dec.nodeType === 'IndexAccess') {
const mappingKeyName = NodePath.getPath(dec).scope.getMappingKeyName(dec);
Expand All @@ -78,13 +83,14 @@ const collectIncrements = (bpg: BoilerplateGenerator) => {
precedingOperator: dec.precedingOperator,
});

if (!stateVarIndicator.decrements[1] && !stateVarIndicator.increments[0]) {
incrementsString += `${modName}`;
if (counter != dec.counter) {
incrementsString[dec.counter + incCounter] = `${modName}`;
} else {
// if we have decrements, this str represents the value we must take away
// => it's a positive value with +'s
incrementsString += ` + ${modName}`;
incrementsString[dec.counter + incCounter] += `${dec.precedingOperator} ${modName}`;
}
counter = dec.counter;
}

return { incrementsArray, incrementsString };
Expand Down Expand Up @@ -222,8 +228,10 @@ class BoilerplateGenerator {
this.assignIndicators(mappingKeyIndicator);
this.mappingKeyName = mappingKeyName.replace('[', '_').replace(']', '');
if (this.mappingKeyName.split('.').length > 2) this.mappingKeyName.replace('.', 'dot');
if(this.mappingKeyName == 'msg')
this.mappingKeyName = this.mappingKeyName+mappingKeyIndicator.keyPath.parent.memberName.replace('sender','Sender').replace('value','Value');
this.mappingName = this.indicators.name;
this.name = `${this.mappingName}_${mappingKeyName}`.replaceAll('.', 'dot').replace('[', '_').replace(']', '');
this.name = `${this.mappingName}_${this.mappingKeyName}`.replaceAll('.', 'dot').replace('[', '_').replace(']', '');
}

generateBoilerplateStatement(bpType: string, extraParams?: any) {
Expand All @@ -232,7 +240,6 @@ class BoilerplateGenerator {
const { mappingKeyName } = extraParams;
this.refresh(mappingKeyName);
}

return {
nodeType: 'BoilerplateStatement',
bpSection: 'statements',
Expand Down Expand Up @@ -376,18 +383,24 @@ class BoilerplateGenerator {
});

/** Partitioned states need boilerplate for an incrementation/decrementation, because it's so weird and different from `a = a - b`. Whole states inherit directly from the AST, so don't need boilerplate here. */
incrementation = () => {
incrementation = (extraParams) => {
//const startIndex = this.getIndex({ addendId });
return {
// startIndex,
newCommitmentValue: this.newCommitmentValue,
structProperties: (this.isStruct && { structProperties: this.structProperties}),
memberName: extraParams.memberName,
addend: {},
};
};

decrementation = () => {
decrementation = (extraParams) => {
//const startIndex = this.getIndex({ subtrahendId });
return {
// startIndex,
newCommitmentValue: this.newCommitmentValue,
structProperties: (this.isStruct && { structProperties: this.structProperties}),
memberName: extraParams.memberName,
subtrahend: {},
};
};
Expand Down
94 changes: 63 additions & 31 deletions src/boilerplate/circuit/zokrates/raw/BoilerplateGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -310,19 +310,40 @@ class BoilerplateGenerator {
];
},

preStatements({ name: x, id, isMapping }): string[] {
if (isMapping) return [];
return [
`
preStatements({ name: x, id, isMapping, isWhole, isNullified, typeName, structProperties }): string[] {
if (isMapping && isWhole) return [];
let decLine = '';
let stateVarIdLine = ``;
if (!isMapping) stateVarIdLine = `
// We need to hard-code each stateVarId into the circuit:
field ${x}_stateVarId_field = ${id}`;
if (!isWhole && isNullified) {
const i = parseInt(x.slice(-1), 10);
const x0 = x.slice(0, -1) + `${i-2}`;
const x1 = x.slice(0, -1) + `${i-1}`;
const x_name = x.slice(0, -2);
let type = typeName ? typeName : 'field';
decLine = `${type} ${x_name} = ${structProperties ? `${type} {${structProperties.map(p => ` ${p}: ${x0}.${p} + ${x1}.${p}`)}}` :`${x0} + ${x1}`} `;
} else if (!isWhole){
const x_name = x.slice(0, -2);
let type = typeName ? typeName : 'field';
decLine = `${type} ${x_name} = ${structProperties ? `${type} {${structProperties.map(p => ` ${p}: 0`)}}` :`0`} `;
} else{
return [`
// We need to hard-code each stateVarId into the circuit:
field ${x}_stateVarId_field = ${id}`,
field ${x}_stateVarId_field = ${id}`];
}
return [
`${decLine}
\n
${stateVarIdLine}`,
// TODO: this results in unnecessary unpacking constraints, but simplifies transpilation effort, for now.
];
},

postStatements({ name: x, isWhole, isNullified, newCommitmentValue, structProperties, structPropertiesTypes, typeName }): string[] {
// if (!isWhole && !newCommitmentValue) throw new Error('PATH');
const y = isWhole ? x : newCommitmentValue;
let y = isWhole ? x : x.slice(0, -2);
const lines: string[] = [];
if (!isWhole && isNullified) {
// decrement
Expand All @@ -331,18 +352,18 @@ class BoilerplateGenerator {
const x1 = x.slice(0, -1) + `${i-1}`;
if (!structProperties) {
lines.push(
`assert(${x0} + ${x1} > ${y})
`assert(${y} >0)
// TODO: assert no under/overflows
field ${x}_newCommitment_value_field = (${x0} + ${x1}) - (${y})`
field ${x}_newCommitment_value_field = ${y}`
);
} else {
// TODO types for each structProperty
lines.push(
`${structProperties.map(p => newCommitmentValue[p] === '0' ? '' : `assert(${x0}.${p} + ${x1}.${p} >= ${y[p]})`).join('\n')}
`${structProperties.map(p => newCommitmentValue[p] === '0' ? '' : `assert(${y}.${p} > 0)`).join('\n')}
// TODO: assert no under/overflows
${typeName} ${x}_newCommitment_value = ${typeName} { ${structProperties.map(p => ` ${p}: (${x0}.${p} + ${x1}.${p}) - (${y[p]})`)} }`
${typeName} ${x}_newCommitment_value = ${typeName} { ${structProperties.map(p => ` ${p}: ${y}.${p}`)} }`
);
}
} else {
Expand All @@ -355,7 +376,7 @@ class BoilerplateGenerator {

}
else {
lines.push(`${typeName} ${x}_newCommitment_value = ${typeName} { ${structProperties.map(p => ` ${p}: ${isWhole ? `${y}.${p}` : `${y[p]}`}`)} }\n`);
lines.push(`${typeName} ${x}_newCommitment_value = ${typeName} { ${structProperties.map(p => ` ${p}: ${y}.${p}`)} }\n`);
if (structPropertiesTypes) {
structPropertiesTypes.forEach(property => {
if (property.typeName === 'bool'){
Expand Down Expand Up @@ -508,23 +529,22 @@ class BoilerplateGenerator {
importStatements(): string[] {
return []; // TODO: we might eventually import some underflow/overflow functions.
},

statements({ name: x}): string[] {
// let y = codeGenerator(addends[0]);
//
// for (const addend of addends) {
// if (addend !== addend[0])
// y += `${addend.precedingOperator} ${codeGenerator(addend)}`;
// }


return [
`// Skipping incrementation of ${x}`
statements({ name: x, addend, newCommitmentValue, structProperties, memberName}): string[] {
if (addend.incrementType === '+='){
if (structProperties) {
return [`${x}.${memberName} = ${x}.${memberName} + ${newCommitmentValue}`]
}
return [`${x} = ${x} + ${newCommitmentValue}`];
} else if (addend.incrementType === '='){
if (structProperties) {
return [`${x}.${memberName} = ${newCommitmentValue}`]
}
return [`${x} = ${newCommitmentValue}`];
}
//return [
// `// Skipping incrementation of ${x}`
// `
// // The below represents the incrementation '${x} = ${x} + ${y}':
//
// field ${x}_${i} = ${y}`,
];
//];
},
};

Expand All @@ -534,23 +554,35 @@ class BoilerplateGenerator {
return []; // TODO: we might eventually import some underflow/overflow functions.
},

statements({ name: x }): string[] {
statements({ name: x, subtrahend, newCommitmentValue, structProperties, memberName}): string[] {
if (subtrahend.decrementType === '-='){
if (structProperties) {
return [`${x}.${memberName} = ${x}.${memberName} - (${newCommitmentValue})`]
}
return [`${x} = ${x} - (${newCommitmentValue})`];
} else if (subtrahend.decrementType === '='){
if (structProperties) {
return [`${x}.${memberName} = ${newCommitmentValue}`]
}
return [`${x} = ${newCommitmentValue}`];
}

// const y = codeGenerator(subtrahend);
// let i = startIndex;
// const x0 = `${x}_${i++}`;
// const x1 = `${x}_${i++}`;
// const x2 = `${x}_${i}`;

return [
`// Moved decrementation of ${x}`
//return [
//`// Moved decrementation of ${x}`
// `
// // The below represents the decrementation '${x} = ${x} - ${y}':
//
// assert(${x0} + ${x1} > ${y})
// // TODO: assert no under/overflows
//
// field ${x2} = (${x0} + ${x1}) - ${y}`,
];
//];
},
};
internalFunctionCall = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ class ContractBoilerplateGenerator {
uint256[] memory inputs = new uint256[](${[
'customInputs.length',
...(newNullifiers ? ['newNullifiers.length'] : []),
...(commitmentRoot ? ['(newNullifiers.length > 0 ? 3 : 0)'] : []), // newNullifiers and commitmentRoot are always submitted together (regardless of use case). It's just that nullifiers aren't always stored (when merely accessing a state). and commitmentRoot are always submitted together (regardless of use case). It's just that nullifiers aren't always stored (when merely accessing a state).
...(commitmentRoot ? ['(newNullifiers.length > 0 ? 3 : 0) + (((_inputs.nullifierRoot != 0) && (_inputs.latestNullifierRoot == 0)) ? 2 : 0)'] : []), // If there are new nullifiers then we need the nullier root, the latest nullifier root and the commitment root, but if the nullifier root is included but not the latest nullifier root (i.e. there is an accessed only state variable) then we only need 2 inputs.
...(newCommitments ? ['newCommitments.length'] : []),
...(encryptionRequired ? ['encInputsLen'] : []),
].join(' + ')});`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,17 +77,22 @@ export function buildPrivateStateNode(nodeType: string, fields: any = {}): any {
}
case 'MembershipWitness': {
const {
id,
increment,
privateStateName,
accessedOnly,
indicator = {},
} = fields;
return {
increment,
stateVarId: id,
isSharedSecret: indicator.isSharedSecret,
privateStateName,
accessedOnly,
isWhole: indicator.isWhole,
isPartitioned: indicator.isPartitioned,
structProperties: indicator.isStruct ? Object.keys(indicator.structProperties) : null,
mappingName: indicator.isMapping ? indicator.node?.name : null,
};
}
case 'CalculateNullifier': {
Expand All @@ -98,7 +103,6 @@ export function buildPrivateStateNode(nodeType: string, fields: any = {}): any {
isSharedSecret: indicator.isSharedSecret,
isWhole: indicator.isWhole,
isPartitioned: indicator.isPartitioned,

};
}
case 'CalculateCommitment': {
Expand Down
Loading

0 comments on commit 0743cea

Please sign in to comment.