diff --git a/circuit/codex/sample_cells.circom b/circuit/codex/sample_cells.circom index cb03e92..6a1d2ff 100644 --- a/circuit/codex/sample_cells.circom +++ b/circuit/codex/sample_cells.circom @@ -112,7 +112,7 @@ log("top root check = ", mtop.recRoot == dataSetRoot); // // then we prove the individual sampled cells - component lg = Log2(maxDepth); // we allow at most 2^32 cells per slot + component lg = Log2_CircomWitnessCalc_Hack(maxDepth); // we allow at most 2^32 cells per slot lg.inp <== nCellsPerSlot; // NOTE: in general we need for the Merkle prover the binary decomposition diff --git a/circuit/lib/log2.circom b/circuit/lib/log2.circom index bb5d626..2cfa5c2 100644 --- a/circuit/lib/log2.circom +++ b/circuit/lib/log2.circom @@ -36,6 +36,60 @@ template Log2(n) { 0 === (mask[i] - mask[i+1]) * (i + 1 - out); } + inp === sum; +} + +//------------------------------------------------------------------------------ +// +// a version of `Log2(n)` which works with `circom-witnesscalc` +// +// yeah this is very ugly. Direct your complaints to the iden3 people. ¯\_(ツ)_/¯ +// + +template Log2_CircomWitnessCalc_Hack(n) { + + signal input inp; + signal output out; + signal output mask[n+1]; + + // compute the logarithm + // as `circom-witnesscalc` does not support any kind of dynamic computation + // and support for functions, and other things also seems to be limited + // we have to implement this here as a static computation instead + // but even that's not enough for `circom-witnesscalc`! hence this uglyness + var x = inp; + var cnt = -1; + signal done[257]; done[0] <-- 0; // we need *signals* here because `circom-witnesscalc` doesn't work otherwise (seriously...) + signal log2[257]; log2[0] <-- -1; // but hopefully circom will optimize these away... + for(var i=0; i<256; i++) { + var not_done = (done[i] == 0); + var do_switch = (x==0) && not_done; + log2[i+1] <-- not_done ? cnt : log2[i]; + done[i+1] <-- do_switch ? 1 : done[i]; + cnt = cnt + 1; + x = x >> 1; + } + + // mask will be a vector [1,1,1,...1,0,...,0,0] + // which can change only where index == out + + for(var i=0; i<=n; i++) { + mask[i] <-- ((2**i) < inp) ? 1 : 0; + } + + out <-- log2[256]; + + log("Log2 hack: input = ",inp," | logarithm = ",out); + + mask[0] === 1; + mask[n] === 0; + + var sum = 0; + for(var i=0; i