@ -0,0 +1,97 @@ |
|||||
|
pragma circom 2.0.0; |
||||
|
|
||||
|
include "utils/row_hasher.circom"; |
||||
|
include "utils/pixels.circom"; |
||||
|
include "node_modules/circomlib/circuits/bitify.circom"; |
||||
|
|
||||
|
|
||||
|
template GrayscaleChecker(n) { |
||||
|
signal input orig[n][3]; |
||||
|
signal input gray[n]; |
||||
|
|
||||
|
signal output n_check; |
||||
|
|
||||
|
component lt[n][2]; |
||||
|
|
||||
|
for (var i = 0; i < n; i++) { |
||||
|
var inter = 299 * orig[i][0] + 587 * orig[i][1] + 114 * orig[i][2]; |
||||
|
|
||||
|
lt[i][0] = LessEqThan(18); |
||||
|
lt[i][1] = LessEqThan(18); |
||||
|
|
||||
|
lt[i][0].in[1] <== 1000; |
||||
|
lt[i][0].in[0] <== inter - 1000 * gray[i]; |
||||
|
lt[i][0].out === 1; |
||||
|
|
||||
|
lt[i][1].in[1] <== 1000; |
||||
|
lt[i][1].in[0] <== 1000 * gray[i] - inter; |
||||
|
lt[i][1].out === 1; |
||||
|
} |
||||
|
n_check <== n; |
||||
|
} |
||||
|
|
||||
|
template GrayScale(width){ |
||||
|
|
||||
|
signal input original[width]; |
||||
|
signal input transformed[width]; |
||||
|
|
||||
|
component decompressor[width]; |
||||
|
component decompressor_grey[width]; |
||||
|
component greychecker[width]; |
||||
|
|
||||
|
for (var j=0; j<width; j++) { |
||||
|
decompressor[j] = Decompressor(); |
||||
|
decompressor[j].in <== original[j]; |
||||
|
|
||||
|
decompressor_grey[j] = DecompressorGrey(); |
||||
|
decompressor_grey[j].in <== transformed[j]; |
||||
|
|
||||
|
greychecker[j] = GrayscaleChecker(10); |
||||
|
greychecker[j].orig <== decompressor[j].out; |
||||
|
greychecker[j].gray <== decompressor_grey[j].out; |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
template GrayScaleHash(width){ |
||||
|
signal input ivc_input[2]; |
||||
|
// signal input prev_orig_hash; |
||||
|
// signal input prev_gray_hash; |
||||
|
signal output ivc_output[2]; |
||||
|
// signal output next_orig_hash; |
||||
|
// signal output next_gray_hash; |
||||
|
|
||||
|
// Private inputs |
||||
|
signal input external_inputs [2 * width]; |
||||
|
|
||||
|
signal row_orig [width]; |
||||
|
signal row_tran [width]; |
||||
|
|
||||
|
for (var i = 0; i < width; i++) { |
||||
|
row_orig[i] <== external_inputs[i]; |
||||
|
row_tran[i] <== external_inputs[i + width]; |
||||
|
} |
||||
|
|
||||
|
component orig_row_hasher = RowHasher(width); |
||||
|
component gray_row_hasher = RowHasher(width); |
||||
|
component orig_hasher = Hasher(2); |
||||
|
component gray_hasher = Hasher(2); |
||||
|
|
||||
|
orig_row_hasher.img <== row_orig; |
||||
|
orig_hasher.values[0] <== ivc_input[0]; // prev_orig_hash |
||||
|
orig_hasher.values[1] <== orig_row_hasher.hash; |
||||
|
ivc_output[0] <== orig_hasher.hash; // next_orig_hash |
||||
|
|
||||
|
gray_row_hasher.img <== row_tran; |
||||
|
gray_hasher.values[0] <== ivc_input[1]; // prev_gray_hash |
||||
|
gray_hasher.values[1] <== gray_row_hasher.hash; |
||||
|
ivc_output[1] <== gray_hasher.hash; // next_grey_hash |
||||
|
|
||||
|
// grayscale code here ... |
||||
|
component checker = GrayScale(width); |
||||
|
checker.original <== row_orig; |
||||
|
checker.transformed <== row_tran; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
component main { public [ivc_input] } = GrayScaleHash(128); |
@ -0,0 +1,9 @@ |
|||||
|
{ |
||||
|
"name": "circom", |
||||
|
"version": "1.0.0", |
||||
|
"main": "index.js", |
||||
|
"license": "MIT", |
||||
|
"dependencies": { |
||||
|
"circomlib": "^2.0.5" |
||||
|
} |
||||
|
} |
@ -0,0 +1,153 @@ |
|||||
|
pragma circom 2.0.0; |
||||
|
include "../node_modules/circomlib/circuits/bitify.circom"; |
||||
|
include "../node_modules/circomlib/circuits/mux1.circom"; |
||||
|
include "../node_modules/circomlib/circuits/comparators.circom"; |
||||
|
|
||||
|
template Decompressor(){ |
||||
|
signal input in; |
||||
|
signal output out[10][3]; |
||||
|
|
||||
|
component toBits = Num2Bits(240); |
||||
|
component toNum[10][3]; |
||||
|
|
||||
|
toBits.in <== in; |
||||
|
|
||||
|
for (var i=0; i<10; i++) { |
||||
|
for (var j=0; j<3; j++) { |
||||
|
toNum[i][j] = Bits2Num(8); |
||||
|
toNum[i][j].in[0] <== toBits.out[i*24+j*8]; |
||||
|
toNum[i][j].in[1] <== toBits.out[i*24+j*8+1]; |
||||
|
toNum[i][j].in[2] <== toBits.out[i*24+j*8+2]; |
||||
|
toNum[i][j].in[3] <== toBits.out[i*24+j*8+3]; |
||||
|
toNum[i][j].in[4] <== toBits.out[i*24+j*8+4]; |
||||
|
toNum[i][j].in[5] <== toBits.out[i*24+j*8+5]; |
||||
|
toNum[i][j].in[6] <== toBits.out[i*24+j*8+6]; |
||||
|
toNum[i][j].in[7] <== toBits.out[i*24+j*8+7]; |
||||
|
out[i][j] <== toNum[i][j].out; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
template DecompressorKernel(kernel_size){ |
||||
|
signal input in; |
||||
|
signal output out[kernel_size][kernel_size]; |
||||
|
|
||||
|
component toBits = Num2Bits(kernel_size*kernel_size*9); // 8-bit value, 1-bit sign |
||||
|
component toNum[kernel_size][kernel_size]; |
||||
|
component selector[kernel_size][kernel_size]; |
||||
|
|
||||
|
toBits.in <== in; |
||||
|
|
||||
|
for (var i=0; i<kernel_size; i++) { |
||||
|
for (var j=0; j<kernel_size; j++) { |
||||
|
toNum[i][j] = Bits2Num(8); |
||||
|
toNum[i][j].in[0] <== toBits.out[i*kernel_size*9+j*9]; |
||||
|
toNum[i][j].in[1] <== toBits.out[i*kernel_size*9+j*9+1]; |
||||
|
toNum[i][j].in[2] <== toBits.out[i*kernel_size*9+j*9+2]; |
||||
|
toNum[i][j].in[3] <== toBits.out[i*kernel_size*9+j*9+3]; |
||||
|
toNum[i][j].in[4] <== toBits.out[i*kernel_size*9+j*9+4]; |
||||
|
toNum[i][j].in[5] <== toBits.out[i*kernel_size*9+j*9+5]; |
||||
|
toNum[i][j].in[6] <== toBits.out[i*kernel_size*9+j*9+6]; |
||||
|
toNum[i][j].in[7] <== toBits.out[i*kernel_size*9+j*9+7]; |
||||
|
|
||||
|
var value = toNum[i][j].out; // value |
||||
|
var sign = toBits.out[i*kernel_size*9+j*9+8]; // sign |
||||
|
|
||||
|
selector[i][j] = Mux1(); |
||||
|
selector[i][j].c[0] <== value; |
||||
|
selector[i][j].c[1] <== 0 - value; |
||||
|
selector[i][j].s <== sign; |
||||
|
|
||||
|
out[i][j] <== selector[i][j].out; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
template DecompressorGrey(){ |
||||
|
signal input in; |
||||
|
signal output out[10]; |
||||
|
|
||||
|
component toBits = Num2Bits(240); |
||||
|
component toNum[10]; |
||||
|
|
||||
|
toBits.in <== in; |
||||
|
|
||||
|
for (var i=0; i<10; i++) { |
||||
|
var j=0; |
||||
|
toNum[i] = Bits2Num(8); |
||||
|
toNum[i].in[0] <== toBits.out[i*24]; |
||||
|
toNum[i].in[1] <== toBits.out[i*24+1]; |
||||
|
toNum[i].in[2] <== toBits.out[i*24+2]; |
||||
|
toNum[i].in[3] <== toBits.out[i*24+3]; |
||||
|
toNum[i].in[4] <== toBits.out[i*24+4]; |
||||
|
toNum[i].in[5] <== toBits.out[i*24+5]; |
||||
|
toNum[i].in[6] <== toBits.out[i*24+6]; |
||||
|
toNum[i].in[7] <== toBits.out[i*24+7]; |
||||
|
out[i] <== toNum[i].out; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
template CompressorCrop(){ |
||||
|
signal input in[10]; |
||||
|
signal output out; |
||||
|
|
||||
|
component toNum = Bits2Num(240); |
||||
|
component toBits[10]; |
||||
|
|
||||
|
for (var i=0; i<10; i++) { |
||||
|
toBits[i] = Num2Bits(24); |
||||
|
toBits[i].in <== in[i]; |
||||
|
for (var j=0; j<24; j++) { |
||||
|
toNum.in[i*24+j] <== toBits[i].out[j]; |
||||
|
} |
||||
|
} |
||||
|
out <== toNum.out; |
||||
|
} |
||||
|
|
||||
|
template DecompressorCrop(){ |
||||
|
signal input in; |
||||
|
signal output out[10]; |
||||
|
|
||||
|
component decomp = DecompressorGrey(); |
||||
|
|
||||
|
decomp.in <== in; |
||||
|
out <== decomp.out; |
||||
|
} |
||||
|
|
||||
|
template CropInfoDecompressor(){ |
||||
|
|
||||
|
signal input in; |
||||
|
signal output row_index; |
||||
|
signal output x; |
||||
|
signal output y; |
||||
|
|
||||
|
component toBits = Num2Bits(36); |
||||
|
component toNumX = Bits2Num(12); |
||||
|
component toNumY = Bits2Num(12); |
||||
|
component toNumIndex = Bits2Num(12); |
||||
|
|
||||
|
toBits.in <== in; |
||||
|
for (var i=0; i<12; i++) { |
||||
|
toNumX.in[i] <== toBits.out[i]; |
||||
|
toNumY.in[i] <== toBits.out[i+12]; |
||||
|
toNumIndex.in[i] <== toBits.out[i+24]; |
||||
|
} |
||||
|
|
||||
|
x <== toNumX.out; |
||||
|
y <== toNumY.out; |
||||
|
row_index <== toNumIndex.out; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
template Test () { |
||||
|
signal input sig1; |
||||
|
signal input sig2; |
||||
|
|
||||
|
component decom = Decompressor(); |
||||
|
decom.in <== sig1; |
||||
|
sig2 === decom.out[2][2]; |
||||
|
} |
||||
|
|
||||
|
// component main = Test(); |
@ -0,0 +1,30 @@ |
|||||
|
pragma circom 2.0.0; |
||||
|
include "../node_modules/circomlib/circuits/poseidon.circom"; |
||||
|
|
||||
|
template Hasher(inputSize) { |
||||
|
signal input values[inputSize]; |
||||
|
signal output hash; |
||||
|
|
||||
|
component hasher = Poseidon(inputSize); |
||||
|
for (var i = 0; i < inputSize; i++) { |
||||
|
hasher.inputs[i] <== values[i]; |
||||
|
} |
||||
|
hash <== hasher.out; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
template RowHasher (width) { |
||||
|
signal input img[width]; |
||||
|
signal output hash; |
||||
|
|
||||
|
component hasher[width-1]; |
||||
|
|
||||
|
for(var i=0; i < width-1; i++) { |
||||
|
hasher[i] = Hasher(2); |
||||
|
hasher[i].values[0] <== i == 0 ? img[0] : hasher[i-1].hash; |
||||
|
hasher[i].values[1] <== img[i+1]; |
||||
|
} |
||||
|
|
||||
|
hash <== hasher[width-2].hash; |
||||
|
|
||||
|
} |