diff --git a/circuits/sha256_test512.circom b/circuits/sha256_test512.circom new file mode 100644 index 0000000..885270e --- /dev/null +++ b/circuits/sha256_test512.circom @@ -0,0 +1,5 @@ +pragma circom 2.0.0; + +include "../node_modules/circomlib/circuits/sha256/sha256.circom"; + +component main = Sha256(512); diff --git a/circuits/storer.circom b/circuits/storer.circom new file mode 100644 index 0000000..ed406a8 --- /dev/null +++ b/circuits/storer.circom @@ -0,0 +1,62 @@ +pragma circom 2.0.0; + +include "../node_modules/circomlib/circuits/sha256/sha256.circom"; +include "../node_modules/circomlib/circuits/poseidon.circom"; +include "tree.circom"; + +template HashCheck(blockSize) { + signal input block[blockSize]; + //signal input blockHash[256]; + signal input blockHash; + + //component hash = Sha256(blockSize); + component hash = Poseidon(blockSize); + for (var i = 0; i < blockSize; i++) { + hash.inputs[i] <== block[i]; + } + hash.out === blockHash; //is this checking the whole array? + // is this enough or do we need output? +} + +template StorageProver(blockSize, qLen, nLevels) { + // blockSize: size of block in bits (sha256), or in ?symbols? (Poseidon) + // qLen: query length, i.e. number if indices to be proven + // nLevels: size of Merkle Tree in the manifest + signal input chunks[qLen][blockSize]; + //signal input chunkHashes[qLen][256]; + signal input chunkHashes[qLen]; + signal input indices[qLen]; + signal input treePathIndices[qLen][nLevels]; + signal input treeSiblings[qLen][nLevels]; + + signal input root; + + //check that chunks hash to given hashes + component hashCheck[qLen]; + for (var i = 0; i < qLen; i++) { + hashCheck[i] = HashCheck(blockSize); + hashCheck[i].block <== chunks[i]; + hashCheck[i].blockHash <== chunkHashes[i]; + } + + //check that the tree is correct + // - check indices against limits + // - convert indices to treePathIndices + // - check chunkHash and treeSiblings according to treePathIndices against root + + component inclusionProofs[qLen]; + //component inclusionProofs[qLen] = MerkleTreeInclusionProof(nLevels); + for (var i = 0; i < qLen; i++) { + inclusionProofs[i] = MerkleTreeInclusionProof(nLevels); + inclusionProofs[i].leaf <== chunkHashes[i]; + for (var j = 0; j < nLevels; j++) { + inclusionProofs[i].siblings[j] <== treeSiblings[i][j]; + inclusionProofs[i].pathIndices[j] <== treePathIndices[i][j]; + } + root === inclusionProofs[i].root; + } +} + +//component main {public [blockHash]} = HashCheck(512); +//component main {public [indices]} = StorageProver(512, 1, 10); +component main {public [indices]} = StorageProver(2, 10, 10); diff --git a/circuits/tree.circom b/circuits/tree.circom new file mode 100644 index 0000000..3ef695f --- /dev/null +++ b/circuits/tree.circom @@ -0,0 +1,45 @@ +pragma circom 2.0.0; + +//based on Semaphore code + +include "../node_modules/circomlib/circuits/poseidon.circom"; +include "../node_modules/circomlib/circuits/mux1.circom"; + +template MerkleTreeInclusionProof(nLevels) { + signal input leaf; + signal input pathIndices[nLevels]; + signal input siblings[nLevels]; + + signal output root; + + component hashers[nLevels]; + component mux[nLevels]; + + signal hashes[nLevels + 1]; + hashes[0] <== leaf; + + for (var i = 0; i < nLevels; i++) { + pathIndices[i] * (1 - pathIndices[i]) === 0; + + hashers[i] = Poseidon(2); + mux[i] = MultiMux1(2); + + mux[i].c[0][0] <== hashes[i]; + mux[i].c[0][1] <== siblings[i]; + + mux[i].c[1][0] <== siblings[i]; + mux[i].c[1][1] <== hashes[i]; + + mux[i].s <== pathIndices[i]; + + hashers[i].inputs[0] <== mux[i].out[0]; + hashers[i].inputs[1] <== mux[i].out[1]; + + hashes[i + 1] <== hashers[i].out; + } + + root <== hashes[nLevels]; +} + +//component main {public [leaf]} = MerkleTreeInclusionProof(10); +