mirror of
https://github.com/logos-storage/logos-storage-proofs-circuits.git
synced 2026-01-02 13:33:07 +00:00
77 lines
2.6 KiB
Plaintext
77 lines
2.6 KiB
Plaintext
pragma circom 2.0.0;
|
|
|
|
include "poseidon2_hash.circom";
|
|
|
|
include "merkle.circom";
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
//
|
|
// calculates a single cell's hash and reconstructs the Merkle root,
|
|
// checking whether it matches the given slot root
|
|
//
|
|
// parameters:
|
|
// - nFieldElemsPerCell: how many field elements a cell consists of (= 2048/31 = 67)
|
|
// - botDepth: the depth of the per-block minitree (= 5)
|
|
// - maxDepth: the maximum depth of slot subtree (= 32)
|
|
//
|
|
// inputs and outputs:
|
|
// - indexBits: the linear index of the cell, within the slot subtree, in binary
|
|
// - lastBits: the index of the last cell (size - 1), in binary (required for odd-even node key)
|
|
// - maskBits: the binary mask of the size rounded up to a power of two
|
|
// - data: the cell data (already encoded as field elements)
|
|
// - merklePath: the Merkle inclusion proof
|
|
// - slotRoot: the expected slot root
|
|
//
|
|
// NOTE: we don't check whether the bits are really bits, that's the
|
|
// responsability of the caller!
|
|
//
|
|
|
|
template ProveSingleCell( nFieldElemsPerCell, botDepth, maxDepth ) {
|
|
|
|
signal input slotRoot;
|
|
signal input data[ nFieldElemsPerCell ];
|
|
signal input lastBits [ maxDepth ];
|
|
signal input indexBits [ maxDepth ];
|
|
signal input maskBits [ maxDepth + 1 ];
|
|
signal input merklePath[ maxDepth ];
|
|
|
|
// these will reconstruct the Merkle path up to the slot root
|
|
// in two steps: first the block-level ("bottom"), then the slot-level ("middle")
|
|
component pbot = RootFromMerklePath( botDepth );
|
|
component pmid = RootFromMerklePath( maxDepth - botDepth );
|
|
|
|
for(var i=0; i<maxDepth; i++) {
|
|
if (i<botDepth) {
|
|
pbot.pathBits[i] <== indexBits[i];
|
|
pbot.maskBits[i] <== maskBits[i];
|
|
pbot.lastBits[i] <== lastBits[i];
|
|
pbot.merklePath[i] <== merklePath[i];
|
|
}
|
|
else {
|
|
var j = i - botDepth;
|
|
pmid.pathBits[j] <== indexBits[i];
|
|
pmid.maskBits[j] <== maskBits[i];
|
|
pmid.lastBits[j] <== lastBits[i];
|
|
pmid.merklePath[j] <== merklePath[i];
|
|
}
|
|
}
|
|
pbot.maskBits[ botDepth ] <== 0;
|
|
pmid.maskBits[ maxDepth - botDepth ] <== 0;
|
|
|
|
// compute the cell hash
|
|
component hash = Poseidon2_hash_rate2( nFieldElemsPerCell );
|
|
hash.inp <== data;
|
|
hash.out ==> pbot.leaf;
|
|
pmid.leaf <== pbot.recRoot;
|
|
|
|
log("middle bottom root check = ", pmid.recRoot == slotRoot);
|
|
|
|
// check if the reconstructed root matches the actual slot root
|
|
pmid.recRoot === slotRoot;
|
|
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
|