Skip to content

Commit 5a4ad7a

Browse files
authored
Merge pull request #452 from EYBlockchain/lyd/joinSplitError
join/split commitments bug
2 parents 7db0905 + af77383 commit 5a4ad7a

File tree

11 files changed

+317
-122
lines changed

11 files changed

+317
-122
lines changed

apitest.js

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -897,17 +897,17 @@ describe('CharityPot Zapp', () => {
897897
).to.equal(0);
898898
expect(
899899
parseInt(res.CharityPot[1].body.tx.returnValues.minLeafIndex, 10),
900-
).to.equal(3);
900+
).to.equal(1);
901901
expect(
902902
parseInt(res.CharityPot[2].body.tx.returnValues.minLeafIndex, 10),
903-
).to.equal(7);
903+
).to.equal(3);
904904
expect(
905905
parseInt(res.CharityPot[3].body.tx.returnValues.minLeafIndex, 10),
906-
).to.equal(9);
906+
).to.equal(5);
907907
});
908908
it('Check number of commitments', async () => {
909909
expect(res.CharityPot[4].body.commitments.length).to.equal(3);
910-
expect(res.CharityPot[5].body.commitments.length).to.equal(8);
910+
expect(res.CharityPot[5].body.commitments.length).to.equal(4);
911911
});
912912
it('Check nullified commitments', async () => {
913913
expect(res.CharityPot[4].body.commitments[0].isNullified).to.equal(true);
@@ -916,31 +916,22 @@ describe('CharityPot Zapp', () => {
916916
expect(res.CharityPot[5].body.commitments[0].isNullified).to.equal(true);
917917
expect(res.CharityPot[5].body.commitments[1].isNullified).to.equal(true);
918918
expect(res.CharityPot[5].body.commitments[2].isNullified).to.equal(true);
919-
expect(res.CharityPot[5].body.commitments[3].isNullified).to.equal(true);
920-
expect(res.CharityPot[5].body.commitments[4].isNullified).to.equal(true);
921-
expect(res.CharityPot[5].body.commitments[5].isNullified).to.equal(true);
922-
expect(res.CharityPot[5].body.commitments[6].isNullified).to.equal(false);
923-
expect(res.CharityPot[5].body.commitments[7].isNullified).to.equal(false);
919+
expect(res.CharityPot[5].body.commitments[3].isNullified).to.equal(false);
924920
});
925921
it('Check value of final commitment', async () => {
926922
expect(
927923
parseInt(res.CharityPot[4].body.commitments[2].preimage.value, 10),
928924
).to.equal(13);
929925
expect(
930-
parseInt(res.CharityPot[5].body.commitments[6].preimage.value, 10),
931-
).to.equal(30);
932-
expect(
933-
parseInt(res.CharityPot[5].body.commitments[7].preimage.value, 10),
934-
).to.equal(7);
926+
parseInt(res.CharityPot[5].body.commitments[3].preimage.value, 10),
927+
).to.equal(37);
935928
});
936-
// Note: commitments that are created and immediately nullified during
937-
// join and split commitments are not restored by backupDataRetriever
938929
it('Check commitments are correct after deleting and restoring from backup', async () => {
939930
expect(res.CharityPot[7].body.commitments.length).to.equal(7);
940931
expect(res.CharityPot[7].body.commitments[0].isNullified).to.equal(true);
941932
expect(res.CharityPot[7].body.commitments[1].isNullified).to.equal(true);
942933
expect(res.CharityPot[7].body.commitments[2].isNullified).to.equal(true);
943-
expect(res.CharityPot[7].body.commitments[3].isNullified).to.equal(false);
934+
expect(res.CharityPot[7].body.commitments[3].isNullified).to.equal(true);
944935
expect(res.CharityPot[7].body.commitments[4].isNullified).to.equal(true);
945936
expect(res.CharityPot[7].body.commitments[5].isNullified).to.equal(false);
946937
expect(res.CharityPot[7].body.commitments[6].isNullified).to.equal(false);

src/boilerplate/orchestration/javascript/nodes/boilerplate-generator.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,28 @@ export function buildPrivateStateNode(nodeType: string, fields: any = {}): any {
7878
: null,
7979
};
8080
}
81+
case 'GetInputCommitments': {
82+
const {
83+
id,
84+
increment,
85+
privateStateName,
86+
accessedOnly,
87+
indicator = {},
88+
} = fields;
89+
return {
90+
increment,
91+
stateVarId: id,
92+
isSharedSecret: indicator.isSharedSecret,
93+
privateStateName,
94+
accessedOnly,
95+
isWhole: indicator.isWhole,
96+
isPartitioned: indicator.isPartitioned,
97+
structProperties: indicator.isStruct
98+
? Object.keys(indicator.structProperties)
99+
: null,
100+
mappingName: indicator.isMapping ? indicator.node?.name : null,
101+
};
102+
}
81103
case 'MembershipWitness': {
82104
const {
83105
id,
@@ -289,6 +311,14 @@ export function buildBoilerplateNode(nodeType: string, fields: any = {}): any {
289311
contractName,
290312
};
291313
}
314+
case 'GetInputCommitments': {
315+
const { contractName, privateStates = {} } = fields;
316+
return {
317+
nodeType,
318+
privateStates,
319+
contractName,
320+
};
321+
}
292322
case 'CalculateNullifier': {
293323
const { privateStates = {} } = fields;
294324
return {

src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts

Lines changed: 78 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -181,22 +181,33 @@ class BoilerplateGenerator {
181181
},
182182
};
183183

184-
membershipWitness = {
185-
postStatements({ stateName,
184+
getInputCommitments = {
185+
postStatements({
186+
stateName,
186187
contractName,
187-
stateType, mappingName, structProperties, isSharedSecret, stateVarIds }): string[] {
188+
stateType,
189+
mappingName,
190+
structProperties,
191+
isSharedSecret,
192+
stateVarIds,
193+
}): string[] {
188194
const stateVarId: string[] = [];
189-
if(stateVarIds.length > 1){
190-
stateVarId.push((stateVarIds[0].split(" = ")[1]).split(";")[0]);
195+
if (stateVarIds.length > 1) {
196+
stateVarId.push(stateVarIds[0].split(' = ')[1].split(';')[0]);
191197
stateVarId.push(`${stateName}_stateVarId_key`);
192-
} else
193-
stateVarId.push(`${stateName}_stateVarId`);
198+
} else stateVarId.push(`${stateName}_stateVarId`);
194199
switch (stateType) {
195200
case 'partitioned':
196201
if (structProperties)
197-
return [`
202+
return [
203+
`
198204
\n\n// First check if required commitments exist or not
199-
\nconst ${stateName}_newCommitmentValue = generalise([${Object.values(structProperties).map((sp) => `generalise(parseInt(${stateName}_${sp}_newCommitmentValue.integer, 10) - parseInt(${stateName}_${sp}_newCommitmentValue_inc.integer, 10))`)}]).all;
205+
\nconst ${stateName}_newCommitmentValue = generalise([${Object.values(
206+
structProperties,
207+
).map(
208+
sp =>
209+
`generalise(parseInt(${stateName}_${sp}_newCommitmentValue.integer, 10) - parseInt(${stateName}_${sp}_newCommitmentValue_inc.integer, 10))`,
210+
)}]).all;
200211
\nlet [${stateName}_commitmentFlag, ${stateName}_0_oldCommitment, ${stateName}_1_oldCommitment] = getInputCommitments(
201212
publicKey.hex(32),
202213
${stateName}_newCommitmentValue.integer,
@@ -207,19 +218,10 @@ class BoilerplateGenerator {
207218
\nlet ${stateName}_witness_0;
208219
\nlet ${stateName}_witness_1;
209220
210-
const ${stateName}_0_prevSalt = generalise(${stateName}_0_oldCommitment.preimage.salt);
211-
const ${stateName}_1_prevSalt = generalise(${stateName}_1_oldCommitment.preimage.salt);
212-
const ${stateName}_0_prev = generalise(${stateName}_0_oldCommitment.preimage.value);
213-
const ${stateName}_1_prev = generalise(${stateName}_1_oldCommitment.preimage.value);
214-
\n\n// generate witness for partitioned state
215-
${stateName}_witness_0 = await getMembershipWitness('${contractName}', generalise(${stateName}_0_oldCommitment._id).integer);
216-
${stateName}_witness_1 = await getMembershipWitness('${contractName}', generalise(${stateName}_1_oldCommitment._id).integer);
217-
const ${stateName}_0_index = generalise(${stateName}_witness_0.index);
218-
const ${stateName}_1_index = generalise(${stateName}_witness_1.index);
219-
const ${stateName}_root = generalise(${stateName}_witness_0.root);
220-
const ${stateName}_0_path = generalise(${stateName}_witness_0.path).all;
221-
const ${stateName}_1_path = generalise(${stateName}_witness_1.path).all;\n`];
222-
return [`
221+
`,
222+
];
223+
return [
224+
`
223225
\n\n// First check if required commitments exist or not
224226
\n${stateName}_newCommitmentValue = generalise(parseInt(${stateName}_newCommitmentValue.integer, 10) - parseInt(${stateName}_newCommitmentValue_inc.integer, 10));
225227
\nlet [${stateName}_commitmentFlag, ${stateName}_0_oldCommitment, ${stateName}_1_oldCommitment] = getInputCommitments(
@@ -251,11 +253,52 @@ class BoilerplateGenerator {
251253
${stateName}_preimage = await getCommitmentsById(${stateName}_stateVarId);
252254
253255
[${stateName}_commitmentFlag, ${stateName}_0_oldCommitment, ${stateName}_1_oldCommitment] = getInputCommitments(
254-
${isSharedSecret ? `sharedPublicKey.hex(32)` : `publicKey.hex(32)`},
256+
${
257+
isSharedSecret
258+
? `sharedPublicKey.hex(32)`
259+
: `publicKey.hex(32)`
260+
},
255261
${stateName}_newCommitmentValue.integer,
256262
${stateName}_preimage,
257263
);
258264
}
265+
`,
266+
];
267+
default:
268+
throw new TypeError(stateType);
269+
}
270+
},
271+
};
272+
273+
membershipWitness = {
274+
postStatements({
275+
stateName,
276+
contractName,
277+
stateType,
278+
mappingName,
279+
structProperties,
280+
isSharedSecret,
281+
stateVarIds,
282+
}): string[] {
283+
switch (stateType) {
284+
case 'partitioned':
285+
if (structProperties)
286+
return [
287+
`
288+
const ${stateName}_0_prevSalt = generalise(${stateName}_0_oldCommitment.preimage.salt);
289+
const ${stateName}_1_prevSalt = generalise(${stateName}_1_oldCommitment.preimage.salt);
290+
const ${stateName}_0_prev = generalise(${stateName}_0_oldCommitment.preimage.value);
291+
const ${stateName}_1_prev = generalise(${stateName}_1_oldCommitment.preimage.value);
292+
\n\n// generate witness for partitioned state
293+
${stateName}_witness_0 = await getMembershipWitness('${contractName}', generalise(${stateName}_0_oldCommitment._id).integer);
294+
${stateName}_witness_1 = await getMembershipWitness('${contractName}', generalise(${stateName}_1_oldCommitment._id).integer);
295+
const ${stateName}_0_index = generalise(${stateName}_witness_0.index);
296+
const ${stateName}_1_index = generalise(${stateName}_witness_1.index);
297+
const ${stateName}_root = generalise(${stateName}_witness_0.root);
298+
const ${stateName}_0_path = generalise(${stateName}_witness_0.path).all;
299+
const ${stateName}_1_path = generalise(${stateName}_witness_1.path).all;\n`];
300+
return [
301+
`
259302
const ${stateName}_0_prevSalt = generalise(${stateName}_0_oldCommitment.preimage.salt);
260303
const ${stateName}_1_prevSalt = generalise(${stateName}_1_oldCommitment.preimage.salt);
261304
const ${stateName}_0_prev = generalise(${stateName}_0_oldCommitment.preimage.value);
@@ -267,29 +310,34 @@ class BoilerplateGenerator {
267310
const ${stateName}_1_index = generalise(${stateName}_witness_1.index);
268311
const ${stateName}_root = generalise(${stateName}_witness_0.root);
269312
const ${stateName}_0_path = generalise(${stateName}_witness_0.path).all;
270-
const ${stateName}_1_path = generalise(${stateName}_witness_1.path).all;\n`];
313+
const ${stateName}_1_path = generalise(${stateName}_witness_1.path).all;\n`,
314+
];
271315
case 'whole':
272-
return [`
316+
return [
317+
`
273318
\n\n// generate witness for whole state
274319
const ${stateName}_emptyPath = new Array(32).fill(0);
275320
const ${stateName}_witness = ${stateName}_witnessRequired
276321
\t? await getMembershipWitness('${contractName}', ${stateName}_currentCommitment.integer)
277322
\t: { index: 0, path: ${stateName}_emptyPath, root: await getRoot('${contractName}') || 0 };
278323
const ${stateName}_index = generalise(${stateName}_witness.index);
279324
const ${stateName}_root = generalise(${stateName}_witness.root);
280-
const ${stateName}_path = generalise(${stateName}_witness.path).all;\n`];
325+
const ${stateName}_path = generalise(${stateName}_witness.path).all;\n`,
326+
];
281327
case 'accessedOnly':
282-
return [`
328+
return [
329+
`
283330
\n\n// generate witness for whole accessed state
284331
const ${stateName}_witness = await getMembershipWitness('${contractName}', ${stateName}_currentCommitment.integer);
285332
const ${stateName}_index = generalise(${stateName}_witness.index);
286333
const ${stateName}_root = generalise(${stateName}_witness.root);
287-
const ${stateName}_path = generalise(${stateName}_witness.path).all;\n`];
334+
const ${stateName}_path = generalise(${stateName}_witness.path).all;\n`,
335+
];
288336
default:
289337
throw new TypeError(stateType);
290338
}
291-
}
292-
};
339+
},
340+
};
293341

294342
calculateNullifier = {
295343

src/boilerplate/orchestration/javascript/raw/toOrchestration.ts

Lines changed: 48 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -726,16 +726,51 @@ export const OrchestrationCodeBoilerPlate: any = (node: any) => {
726726
],
727727
};
728728

729+
case 'GetInputCommitments':
730+
for ([stateName, stateNode] of Object.entries(node.privateStates)) {
731+
const stateVarIds = stateVariableIds({
732+
privateStateName: stateName,
733+
stateNode,
734+
});
735+
if (node.isConstructor) {
736+
continue;
737+
}
738+
if (stateNode.isPartitioned) {
739+
lines.push(
740+
Orchestrationbp.getInputCommitments.postStatements({
741+
stateName,
742+
contractName: node.contractName,
743+
stateType: 'partitioned',
744+
mappingName: stateNode.mappingName || stateName,
745+
structProperties: stateNode.structProperties,
746+
isSharedSecret: stateNode.isSharedSecret,
747+
stateVarIds,
748+
}),
749+
);
750+
}
751+
}
752+
return {
753+
statements: [
754+
`\n// Get input commitments for partitioned states: \n\n`,
755+
...lines,
756+
],
757+
};
758+
729759
case 'MembershipWitness':
730760
for ([stateName, stateNode] of Object.entries(node.privateStates)) {
731-
const stateVarIds = stateVariableIds({ privateStateName: stateName, stateNode });
761+
const stateVarIds = stateVariableIds({
762+
privateStateName: stateName,
763+
stateNode,
764+
});
732765
if (node.isConstructor) {
733-
lines.push([`
766+
lines.push([
767+
`
734768
const ${stateName}_index = generalise(0);
735769
const ${stateName}_root = generalise(0);
736770
const ${stateName}_path = generalise(new Array(32).fill(0)).all;\n
737-
`]);
738-
continue;
771+
`,
772+
]);
773+
continue;
739774
}
740775
if (stateNode.isPartitioned) {
741776
lines.push(
@@ -746,9 +781,9 @@ export const OrchestrationCodeBoilerPlate: any = (node: any) => {
746781
mappingName: stateNode.mappingName || stateName,
747782
structProperties: stateNode.structProperties,
748783
isSharedSecret: stateNode.isSharedSecret,
749-
stateVarIds
750-
}));
751-
784+
stateVarIds,
785+
}),
786+
);
752787
}
753788
if (stateNode.accessedOnly) {
754789
lines.push(
@@ -759,9 +794,9 @@ export const OrchestrationCodeBoilerPlate: any = (node: any) => {
759794
mappingName: stateNode.mappingName || stateName,
760795
structProperties: stateNode.structProperties,
761796
isSharedSecret: stateNode.isSharedSecret,
762-
stateVarIds
763-
}));
764-
797+
stateVarIds,
798+
}),
799+
);
765800
} else if (stateNode.isWhole) {
766801
lines.push(
767802
Orchestrationbp.membershipWitness.postStatements({
@@ -771,9 +806,9 @@ export const OrchestrationCodeBoilerPlate: any = (node: any) => {
771806
mappingName: stateNode.mappingName || stateName,
772807
structProperties: stateNode.structProperties,
773808
isSharedSecret: stateNode.isSharedSecret,
774-
stateVarIds
775-
}));
776-
809+
stateVarIds,
810+
}),
811+
);
777812
}
778813
}
779814
return {

src/codeGenerators/orchestration/files/toOrchestration.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -486,14 +486,16 @@ const prepareMigrationsFile = (file: localFile, node: any) => {
486486
saveMetadata(erc721Address, 'ERC721', "/Escrow-imports", chainId, blockNumber, deployTx.hash) \n \n`;
487487
break;
488488
case 'ERC1155':
489-
customDeployments += `const ERC1155 = await hre.ethers.getContractFactory('ERC1155Token') \n
490-
const erc1155 = await ERC1155.deploy() \n
489+
customDeployments += `const ERC1155 = await hre.ethers.getContractFactory('ERC1155') \n
490+
const erc1155 = await ERC1155.deploy(
491+
'MyCoinUrl'
492+
) \n
491493
await erc1155.waitForDeployment() \n
492494
erc1155Address = await erc1155.getAddress() \n
493495
console.log('ERC1155 deployed to:', erc1155Address) \n
494496
blockNumber = await hre.ethers.provider.getBlockNumber(); \n
495497
deployTx = await erc1155.deploymentTransaction().wait() \n
496-
saveMetadata(erc1155Address, 'ERC1155Token', "/Escrow-imports", chainId, blockNumber, deployTx.hash) \n
498+
saveMetadata(erc1155Address, 'ERC1155', "/Escrow-imports", chainId, blockNumber, deployTx.hash) \n
497499
\n`;
498500
break;
499501
}

src/codeGenerators/orchestration/nodejs/toOrchestration.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,7 @@ export default function codeGenerator(node: any, options: any = {}): any {
327327
case 'InitialiseKeys':
328328
case 'ReadPreimage':
329329
case 'WritePreimage':
330+
case 'GetInputCommitments':
330331
case 'MembershipWitness':
331332
case 'CalculateNullifier':
332333
case 'CalculateCommitment':

0 commit comments

Comments
 (0)