- We use zkemail for email verification and from address reveal from the header of the email.
Proving contiguous elements in merkle tree
This was an interesting problem that I solved. The logic in js for contruction given the siblings.
A note about siblings that siblings at a level are only two for leftmost and rightmost element in the array.
javascriptstatic async generateRoot(continousSegment: number[], auditPath: bigint[][], height: number, firstIndex: number, lastIndex: number): Promise<bigint> { const mimc = await buildMimc7(); let aboveLayer: bigint[] = []; let currentLayer = continousSegment.map((value) => BigInt(value)); firstIndex = generalisedIndex(firstIndex, height); lastIndex = generalisedIndex(lastIndex, height); for (let y = height; y > 0; y--) { if (firstIndex % 2 !== 0) { currentLayer.unshift(auditPath[y][0]!); firstIndex -= 1; } if (lastIndex % 2 !== 1) { currentLayer.push(auditPath[y][1]!); lastIndex += 1; } for (let x = 0; x < currentLayer.length - 1; x += 2) { const left = currentLayer[x]; const right = currentLayer[x + 1]; const hash = this.hash(left, right, mimc); aboveLayer.push(hash); } currentLayer = aboveLayer; aboveLayer = []; // a generalised index is 2**height + index-> in the array firstIndex = getParentGeneralisedIndex(firstIndex); lastIndex = getParentGeneralisedIndex(lastIndex); } return currentLayer[0]; }
The circuit is available here
Here is a high level diagram of the circuitβs working
javascriptββββββββββββββββββββββββββββββββββββββββββββββββ β GenerateRoot Circuit (Top Layer) β β Reconstructs Merkle Root from segment β ββββββββββββββββββββββββββββββββββββββββββββββββ β² β Reconstructs β layer-by-layer (bottom-up) β ββββββββββββββββββββββββββββββββββββββ β MerkleLayer (one level up) β β ββββββββββββββββββββββββββββββββββ β β 1. AddSiblings if needed β β 2. Hash pairs of nodes β β 3. Calculate new indices β ββββββββββββββββββββββββββββββββββββββ β² β ββββββββββββββββββββββββββββββββββββββ β AddSiblings β β ββββββββββββββββββββββββββββββββββ β β Uses IsOdd / IsEven to decide β β if we prepend/append siblings β ββββββββββββββββββββββββββββββββββββββ β² β ββββββββββββββββ¬βββββββββββββββββββββββββ¬βββββββββββββββ β β β β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β IsOdd(first) β β IsEven(last)β β Siblings[0] β β Siblings[1] β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β β β β ββββββββ¬ββββββββ΄βββββββ¬βββββββββββββββββββ΄βββββββ¬βββββββ β β β βββββββββββββββββββββββββββββββββββββββββββββββββββββββ β Hashing of Pairs β β βββββββββββββββββββββββββββββββββββββββββββββββββββ β β loop i = 0 to N: β β if i+1 < size: β β hash = MiMC(left = arr[i], right = arr[i+1]) β βββββββββββββββββββββββββββββββββββββββββββββββββββββββ β βΌ ββββββββββββββββββββββββββββββββββββββ β GetParentGeneralisedIndex β β ββββββββββββββββββββββββββββββββββ β β idx >> 1 (i.e., idx / 2) β ββββββββββββββββββββββββββββββββββββββ Repeat above `MerkleLayer` for all layers (height times) until root is computed