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

shared secret #237

Merged
merged 26 commits into from
Jun 19, 2024
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions circuits/common/joinCommitments.zok
Original file line number Diff line number Diff line change
Expand Up @@ -93,18 +93,17 @@ def main(\
assert(\
field_to_bool_256(oldCommitment_0_nullifier)[8..256] == field_to_bool_256(oldCommitment_0_nullifier_check_field)[8..256]\
)
assert(\

assert(\
nullifierRoot == checkproof(\
oldCommitment_0_nullifier_nonmembershipWitness_siblingPath,\
oldCommitment_0_nullifier\
) )

assert( newNullifierRoot == checkUpdatedPath(oldCommitment_0_nullifier_nonmembershipWitness_newsiblingPath,\
assert( newNullifierRoot == checkUpdatedPath(\
oldCommitment_0_nullifier_nonmembershipWitness_newsiblingPath,\
oldCommitment_0_nullifier) )





// Nullify oldCommitment_1:

Expand All @@ -124,9 +123,11 @@ def main(\
oldCommitment_1_nullifier\
) )

assert( newNullifierRoot == checkUpdatedPath(oldCommitment_1_nullifier_nonmembershipWitness_newsiblingPath,\
assert( newNullifierRoot == checkUpdatedPath(\
oldCommitment_1_nullifier_nonmembershipWitness_newsiblingPath,\
oldCommitment_1_nullifier) )


// oldCommitment_0_commitment: preimage check

field oldCommitment_0_commitment_field = poseidon([\
Expand Down
Copy link
Contributor

Choose a reason for hiding this comment

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

Is the containsAccessedOnlyStates relevant to this pull request?

Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ class BoilerplateGenerator {
isPartitioned?: boolean;
isNullified?: boolean;
isAccessed?: boolean;
reinitialisable?: boolean;
initialisationRequired?: boolean;
newCommitmentsRequired?: boolean;
encryptionRequired?: boolean;
Expand All @@ -112,12 +113,12 @@ class BoilerplateGenerator {
mappingName: string;
indicators: any;
newCommitmentValue: any;
containsAccessedOnlyStates: boolean


bpSections: string[] = ['importStatements', 'parameters', 'preStatements', 'postStatements'];

constructor(indicators: StateVariableIndicator) {

// Through prior traversals, a BoilerplateGenerator class for this set of indicators might already be stored in memory:
if (bpCache.has(indicators)) return bpCache.get(indicators);

Expand All @@ -140,6 +141,7 @@ class BoilerplateGenerator {
isPartitioned,
isNullified,
isAccessed,
reinitialisable,
newCommitmentsRequired,
isMapping,
isStruct,
Expand All @@ -154,6 +156,7 @@ class BoilerplateGenerator {
isPartitioned,
isNullified,
isAccessed,
reinitialisable,
newCommitmentsRequired,
isMapping,
isStruct,
Expand Down Expand Up @@ -255,6 +258,7 @@ class BoilerplateGenerator {
...(this.typeName && { typeName: this.typeName}),
...(this.mappingKeyName && { mappingKeyTypeName: this.mappingKeyTypeName }),
...(this.isAccessed && { isAccessed: this.isAccessed }),
...(this.reinitialisable && { reinitialisable: this.reinitialisable }),
...(this.initialisationRequired && { initialisationRequired: this.initialisationRequired }),
...(this.newCommitmentValue && { newCommitmentValue: this.newCommitmentValue }),
// ...(this.burnedOnly && { burnedOnly: this.burnedOnly }), // TODO
Expand Down Expand Up @@ -301,6 +305,9 @@ class BoilerplateGenerator {
addBP('oldCommitmentPreimage');
addBP('oldCommitmentExistence');
}
if(this.reinitialisable){
addBP('oldCommitmentPreimage');
}
if (this.newCommitmentsRequired && !this.burnedOnly) {
addBP('newCommitment');
}
Expand Down
12 changes: 8 additions & 4 deletions src/boilerplate/circuit/zokrates/raw/BoilerplateGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,24 +166,27 @@ class BoilerplateGenerator {
];
},

parameters({ name: x, typeName }): string[] {
parameters({ name: x, typeName, reinitialisable }): string[] {
// prettier-ignore
if(!reinitialisable)
return [
`private ${typeName ? typeName : 'field'} ${x}_oldCommitment_value`,
`private field ${x}_oldCommitment_salt`,
];
},

preStatements({ name: x, typeName }): string[] {
preStatements({ name: x, typeName, reinitialisable }): string[] {
// For a state variable, we'll have passed in `${x}_oldCommitment_value` as a parameter. But our AST nodes will be using `${x}`. This line resolves the two.
if (reinitialisable)
return [ `${typeName ? typeName : 'field'} ${x} = 0`];
kKahina marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

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

${x}=0, because commitment are not nullified ?

return [
`
${typeName ? typeName : 'field'} ${x} = ${x}_oldCommitment_value`,
];
},

postStatements({ name: x, structProperties }): string[] {
if (structProperties)
postStatements({ name: x, structProperties, reinitialisable }): string[] {
if (structProperties && !reinitialisable)
return [
`
// ${x}_oldCommitment_commitment: preimage check
Expand All @@ -195,6 +198,7 @@ class BoilerplateGenerator {
${x}_oldCommitment_salt\\
])`,
];
if(!reinitialisable)
return [
`
// ${x}_oldCommitment_commitment: preimage check
Expand Down
30 changes: 30 additions & 0 deletions src/boilerplate/common/commitment-storage.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,22 @@
Logic for storing and retrieving commitments from a mongo DB.
*/
import config from 'config';
import fs from 'fs';
import gen from 'general-number';
import mongo from './mongo.mjs';
import logger from './logger.mjs';
import utils from 'zkp-utils';
import { poseidonHash } from './number-theory.mjs';
import { sharedSecretKey, scalarMult, compressStarlightKey } from './number-theory.mjs';
import { generateProof } from './zokrates.mjs';
import { SumType, reduceTree, toBinArray, poseidonConcatHash } from './smt_utils.mjs';
import { hlt } from './hash-lookup.mjs';

const { MONGO_URL, COMMITMENTS_DB, COMMITMENTS_COLLECTION } = config;
const { generalise } = gen;

const keyDb = '/app/orchestration/common/db/key.json';

const TRUNC_LENGTH = 32; // Just for testing so we don't make more than 32 deep smt trees.
const WHOLE_STATES = [WHOLE_STATE_NAMES];
// structure for SMT
Expand Down Expand Up @@ -879,3 +883,29 @@ export function getupdatedNullifierPaths(nullifier) {
const witness = { path: membershipPath.path, root: root };
return witness;
}

export async function getSharedkeys(
_recipientPublicKey
) {

const keys = JSON.parse(
fs.readFileSync(keyDb, "utf-8", (err) => {
console.log(err);
})
);
const secretKey = generalise(keys.secretKey);
const publicKey = generalise(keys.publicKey);
const recipientPublicKey = generalise(_recipientPublicKey);

let sharedKey = sharedSecretKey(secretKey, recipientPublicKey);
const keyJson = {
secretKey: secretKey.integer,
publicKey: publicKey.integer,
sharedSecretKey: sharedKey[0].integer,
sharedPublicKey: sharedKey[1].integer, // not req
};
fs.writeFileSync(keyDb, JSON.stringify(keyJson, null, 4));

return publicKey;
}

Empty file.
34 changes: 34 additions & 0 deletions src/boilerplate/common/number-theory.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,39 @@ function decrypt(encryptedMessages, secretKey, encPublicKey) {
return plainText;
}


/**
@param {string} secretKey - hex string
@param {string[2]} recipientPublicKey - hex string[]
@return {string} key - int string
*/
function sharedSecretKey(secretKey, recipientPublicKey) {
const publickKeyPoint = decompressStarlightKey(recipientPublicKey);
const sharedSecret = scalarMult(secretKey.hex(32), [
BigInt(generalise(publickKeyPoint[0]).hex(32)),
BigInt(generalise(publickKeyPoint[1]).hex(32)),
]);
const key = poseidonHash([
sharedSecret[0],
sharedSecret[1],
BigInt(DOMAIN_KEM),
]);

let sharePublicKeyPoint = generalise(
scalarMult(key.hex(32), config.BABYJUBJUB.GENERATOR)
);

let yBits = sharePublicKeyPoint[1].binary;
if (yBits.length >= 253)
yBits = yBits.slice(2);
const xBits = sharePublicKeyPoint[0].binary;
const sign = xBits[xBits.length - 1];
let sharedPublicKey = new GN(sign + yBits.padStart(253, "0"), "binary");


return [key, sharedPublicKey];
}

// Implements the Poseidon hash, drawing on the ZoKrates implementation
// roundsP values referred from circom library
// https://github.com/iden3/circomlibjs/blob/main/src/poseidon_opt.js
Expand Down Expand Up @@ -386,4 +419,5 @@ export {
decompressStarlightKey,
decrypt,
poseidonHash,
sharedSecretKey,
};
Original file line number Diff line number Diff line change
Expand Up @@ -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, 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 };
}

const params = path.getFunctionParameters();
Expand Down
Copy link
Contributor

Choose a reason for hiding this comment

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

Are the changes on line 110 and lines 139-141 related to this pull request or are they from when the nullifier checking was being changed?

Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class ContractBoilerplateGenerator {
...(encryptionRequired ? [`
event EncryptedData(uint256[] cipherText, uint256[2] ephPublicKey);`] : []),

...nullifiersRequired ? [`
...nullifiersRequired ? [`
uint256 public newNullifierRoot;`] : [],

...(oldCommitmentAccessRequired ? [`
Expand Down Expand Up @@ -92,6 +92,7 @@ class ContractBoilerplateGenerator {
];
},


registerZKPPublicKey(): string[] {
return [
`
Expand All @@ -106,6 +107,7 @@ class ContractBoilerplateGenerator {
oldCommitmentAccessRequired: commitmentRoot,
nullifiersRequired: newNullifiers,
newCommitmentsRequired: newCommitments,
containsAccessedOnlyState: checkNullifiers,
encryptionRequired,
circuitParams,
constructorContainsSecret,
Expand Down Expand Up @@ -134,6 +136,9 @@ class ContractBoilerplateGenerator {
verifyInput.push( `
inputs[k++] = newNullifiers[${counter.newNullifiers++}];`);
break;
case 'checkNullifier':
verifyInput.push(`
inputs[k++] = checkNullifiers[${counter.checkNullifiers++}];`);
case 'newCommitment':
verifyInput.push(`
inputs[k++] = newCommitments[${counter.newCommitments++}];`);
Expand Down Expand Up @@ -200,7 +205,7 @@ class ContractBoilerplateGenerator {
uint256[] memory inputs = new uint256[](${[
'customInputs.length',
...(newNullifiers ? ['newNullifiers.length'] : []),
...(commitmentRoot ? ['(newNullifiers.length > 0 ? 3 : 0)'] : []), // newNullifiers , nullifierRoots(old and latest) 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)'] : []), // 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).
...(newCommitments ? ['newCommitments.length'] : []),
...(encryptionRequired ? ['encInputsLen'] : []),
].join(' + ')});`,
Expand All @@ -216,6 +221,7 @@ class ContractBoilerplateGenerator {
const counter = {
customInputs: 0,
newNullifiers: 0,
checkNullifiers: 0,
newCommitments: 0,
encryption: 0,
};
Expand Down Expand Up @@ -253,10 +259,10 @@ class ContractBoilerplateGenerator {
}`] :
newCommitments ? [`
insertLeaves(newCommitments);`] :
[]
[]
),

...(newNullifiers) ? [`
...(newNullifiers) ? [`
if (newNullifiers.length > 0) {
newNullifierRoot = _inputs.latestNullifierRoot;
}`] : []
Expand Down Expand Up @@ -307,22 +313,22 @@ class ContractBoilerplateGenerator {
}`)
verifyInputs.push(`

if (functionId == uint(FunctionNames.joinCommitments)) {
if (functionId == uint(FunctionNames.joinCommitments)) {


require(newNullifierRoot == _inputs.nullifierRoot, "Input NullifierRoot does not exist.");

uint k = 0;

inputs[k++] = _inputs.nullifierRoot;
inputs[k++] = _inputs.latestNullifierRoot;
inputs[k++] = newNullifiers[0];
inputs[k++] = newNullifiers[1];
inputs[k++] = _inputs.commitmentRoot;
inputs[k++] = newCommitments[0];
inputs[k++] = 1;
}
require(newNullifierRoot == _inputs.nullifierRoot, "Input NullifierRoot does not exist.");

uint k = 0;

inputs[k++] = _inputs.nullifierRoot;
inputs[k++] = _inputs.latestNullifierRoot;
inputs[k++] = newNullifiers[0];
inputs[k++] = newNullifiers[1];
inputs[k++] = _inputs.commitmentRoot;
inputs[k++] = newCommitments[0];
inputs[k++] = 1;

}

if (functionId == uint(FunctionNames.splitCommitments)) {

Expand Down
Copy link
Contributor

Choose a reason for hiding this comment

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

Is line 63 one of the nullifier changes?

Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,13 @@ class FunctionBoilerplateGenerator {
nullifiersRequired: newNullifiers,
oldCommitmentAccessRequired: commitmentRoot,
newCommitmentsRequired: newCommitments,
containsAccessedOnlyState: checkNullifiers,
encryptionRequired
}): string[] {
// prettier-ignore

let parameter = [
...(customInputs ? customInputs.filter(input => !input.dummy && input.isParam)
...(customInputs ? customInputs.filter(input => !input.dummy && input.isParam)
.map(input => input.structName ? `(${input.properties.map(p => p.type)})` : input.isConstantArray ? `${input.type}[${input.isConstantArray}]` : input.type) : []), // TODO arrays of structs/ structs of arrays
...(newNullifiers ? [`uint256`] : []),
...(newNullifiers ? [`uint256`] : []),
Expand Down Expand Up @@ -113,11 +114,11 @@ class FunctionBoilerplateGenerator {
}).join('\n')}`]
: []),

...(newNullifiers ? [`
inputs.nullifierRoot = nullifierRoot; `] : []),
...(newNullifiers ? [`
inputs.nullifierRoot = nullifierRoot; `] : []),

...(newNullifiers ? [`
inputs.latestNullifierRoot = latestNullifierRoot; `] : []),
...(newNullifiers ? [`
inputs.latestNullifierRoot = latestNullifierRoot; `] : []),


...(newNullifiers ? [`
Expand Down
Loading
Loading