2022-11-17 12:49:58 +00:00
|
|
|
pragma circom 2.0.0;
|
|
|
|
|
|
|
|
include "../node_modules/circomlib/circuits/sha256/sha256.circom";
|
|
|
|
include "../node_modules/circomlib/circuits/poseidon.circom";
|
2022-11-17 12:59:58 +00:00
|
|
|
|
|
|
|
include "../node_modules/circomlib/circuits/bitify.circom";
|
2022-11-17 12:49:58 +00:00
|
|
|
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?
|
|
|
|
}
|
|
|
|
|
2022-11-17 13:23:31 +00:00
|
|
|
template CheckInclusion(nLevels) {
|
|
|
|
signal input index;
|
|
|
|
signal input chunkHash;
|
|
|
|
signal input treeSiblings[nLevels];
|
|
|
|
signal input root;
|
|
|
|
|
|
|
|
component num2Bits = Num2Bits(nLevels);
|
|
|
|
num2Bits.in <== index;
|
|
|
|
|
|
|
|
component inclusionProof = MerkleTreeInclusionProof(nLevels);
|
|
|
|
inclusionProof.leaf <== chunkHash;
|
|
|
|
for (var j = 0; j < nLevels; j++) {
|
|
|
|
inclusionProof.siblings[j] <== treeSiblings[j];
|
|
|
|
inclusionProof.pathIndices[j] <== num2Bits.out[j];
|
|
|
|
}
|
|
|
|
root === inclusionProof.root;
|
|
|
|
}
|
|
|
|
|
2022-11-17 12:49:58 +00:00
|
|
|
template StorageProver(blockSize, qLen, nLevels) {
|
2022-11-17 13:00:16 +00:00
|
|
|
// blockSize: size of block in bits (sha256), or in symbols (Poseidon)
|
2022-11-17 12:49:58 +00:00
|
|
|
// 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 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
|
|
|
|
|
2022-11-17 13:23:31 +00:00
|
|
|
component checkInclusion[qLen];
|
2022-11-17 12:49:58 +00:00
|
|
|
for (var i = 0; i < qLen; i++) {
|
2022-11-17 12:59:58 +00:00
|
|
|
|
2022-11-17 13:23:31 +00:00
|
|
|
checkInclusion[i] = CheckInclusion(nLevels);
|
|
|
|
checkInclusion[i].index <== indices[i];
|
|
|
|
checkInclusion[i].treeSiblings <== treeSiblings[i];
|
|
|
|
checkInclusion[i].chunkHash <== chunkHashes[i];
|
|
|
|
checkInclusion[i].root <== root;
|
2022-11-17 12:49:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//component main {public [blockHash]} = HashCheck(512);
|
|
|
|
//component main {public [indices]} = StorageProver(512, 1, 10);
|
|
|
|
component main {public [indices]} = StorageProver(2, 10, 10);
|