Skip to content

Commit

Permalink
Merge pull request privacy-scaling-explorations#164 from privacy-scal…
Browse files Browse the repository at this point in the history
…ing-explorations/feat/comparators-circuits

feat: add safe comparators templates
  • Loading branch information
ctrlc03 authored Feb 21, 2024
2 parents e62d7be + ff46d66 commit 401a0e5
Show file tree
Hide file tree
Showing 3 changed files with 368 additions and 0 deletions.
24 changes: 24 additions & 0 deletions packages/circuits/circom/circuits.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,29 @@
"template": "Ecdh",
"pubs": ["publicKey"],
"params": []
},
"safe-less-than": {
"file": "safe-comparators",
"template": "SafeLessThan",
"pubs": ["in"],
"params": [252]
},
"safe-less-eq-than": {
"file": "safe-comparators",
"template": "SafeLessEqThan",
"pubs": ["in"],
"params": [252]
},
"safe-greater-than": {
"file": "safe-comparators",
"template": "SafeGreaterThan",
"pubs": ["in"],
"params": [252]
},
"safe-greater-eq-than": {
"file": "safe-comparators",
"template": "SafeGreaterEqThan",
"pubs": ["in"],
"params": [252]
}
}
60 changes: 60 additions & 0 deletions packages/circuits/circom/safe-comparators.circom
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
pragma circom 2.0.0;

include "./bitify.circom";

// Template for safely comparing if one input is less than another,
// ensuring inputs are within a specified bit-length.
template SafeLessThan(n) {
// Ensure the bit-length does not exceed 252 bits.
assert(n <= 252);

signal input in[2];
signal output out;

// Convert both inputs to their bit representations to ensure
// they fit within 'n' bits.
var n2b1[n];
n2b1 = Num2Bits(n)(in[0]);

var n2b2[n];
n2b2 = Num2Bits(n)(in[1]);

// Additional conversion to handle arithmetic operation and capture the comparison result.
var n2b[n+1];
n2b = Num2Bits(n + 1)(in[0] + (1<<n) - in[1]);

// Determine if in[0] is less than in[1] based on the most significant bit.
out <== 1 - n2b[n];
}

// Template to check if one input is less than or equal to another.
template SafeLessEqThan(n) {
signal input in[2];
signal output out;

// Use SafeLessThan to determine if in[0] is less than in[1] + 1.
out <== SafeLessThan(n)([in[0], in[1] + 1]);
}

// Template for safely comparing if one input is greater than another.
template SafeGreaterThan(n) {
// Two inputs to compare.
signal input in[2];
// Output signal indicating comparison result.
signal output out;

// Invert the inputs for SafeLessThan to check if in[1] is less than in[0].
out <== SafeLessThan(n)([in[1], in[0]]);
}

// Template to check if one input is greater than or equal to another.
template SafeGreaterEqThan(n) {
// Two inputs to compare.
signal input in[2];
// Output signal indicating comparison result.
signal output out;

// Invert the inputs and adjust for equality in SafeLessThan to
// check if in[1] is less than or equal to in[0].
out <== SafeLessThan(n)([in[1], in[0] + 1]);
}
284 changes: 284 additions & 0 deletions packages/circuits/tests/safe-comparators.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,284 @@
import { WitnessTester } from "circomkit"
import { circomkit } from "./common"

describe("safe-comparators", () => {
describe("SafeLessThan", () => {
let circuit: WitnessTester<["in"], ["out"]>

it("Should correctly compare two numbers [x, x]", async () => {
// Test values
const inValues = [5, 5] // in[0] === in[1], expecting 'out' to be 0.
const expectedOut = 0 // Since 5 is equal to 5.

const INPUT = {
in: inValues
}

const OUTPUT = {
out: expectedOut
}

circuit = await circomkit.WitnessTester("SafeLessThan", {
file: "safe-comparators",
template: "SafeLessThan",
params: [252] // Assuming we're working within 252-bit numbers.
})

await circuit.expectPass(INPUT, OUTPUT)
})

it("Should correctly compare two numbers [x-1, x]", async () => {
// Test values
const inValues = [5, 6] // in[0] < in[1], expecting 'out' to be 1.
const expectedOut = 1 // Since 5 is less than 6.

const INPUT = {
in: inValues
}

const OUTPUT = {
out: expectedOut
}

circuit = await circomkit.WitnessTester("SafeLessThan", {
file: "safe-comparators",
template: "SafeLessThan",
params: [252] // Assuming we're working within 252-bit numbers.
})

await circuit.expectPass(INPUT, OUTPUT)
})

it("Should correctly compare two numbers [x, x-1]", async () => {
// Test values
const inValues = [6, 5] // in[0] > in[1], expecting 'out' to be 0.
const expectedOut = 0 // Since 6 is greater than 5.

const INPUT = {
in: inValues
}

const OUTPUT = {
out: expectedOut
}

circuit = await circomkit.WitnessTester("SafeLessThan", {
file: "safe-comparators",
template: "SafeLessThan",
params: [252] // Assuming we're working within 252-bit numbers.
})

await circuit.expectPass(INPUT, OUTPUT)
})
})

describe("SafeLessEqThan", () => {
let circuit: WitnessTester<["in"], ["out"]>

it("Should correctly compare two numbers [x, x]", async () => {
// Test values
const inValues = [5, 5] // in[0] === in[1], expecting 'out' to be 1.
const expectedOut = 1 // Since 5 is equal to 5.

const INPUT = {
in: inValues
}

const OUTPUT = {
out: expectedOut
}

circuit = await circomkit.WitnessTester("SafeLessEqThan", {
file: "safe-comparators",
template: "SafeLessEqThan",
params: [252] // Assuming we're working within 252-bit numbers.
})

await circuit.expectPass(INPUT, OUTPUT)
})

it("Should correctly compare two numbers [x-1, x]", async () => {
// Test values
const inValues = [5, 6] // in[0] < in[1], expecting 'out' to be 1.
const expectedOut = 1 // Since 5 is less than 6.

const INPUT = {
in: inValues
}

const OUTPUT = {
out: expectedOut
}

circuit = await circomkit.WitnessTester("SafeLessEqThan", {
file: "safe-comparators",
template: "SafeLessEqThan",
params: [252] // Assuming we're working within 252-bit numbers.
})

await circuit.expectPass(INPUT, OUTPUT)
})

it("Should correctly compare two numbers [x, x-1]", async () => {
// Test values
const inValues = [6, 5] // in[0] > in[1], expecting 'out' to be 0.
const expectedOut = 0 // Since 6 is greater than 5.

const INPUT = {
in: inValues
}

const OUTPUT = {
out: expectedOut
}

circuit = await circomkit.WitnessTester("SafeLessEqThan", {
file: "safe-comparators",
template: "SafeLessEqThan",
params: [252] // Assuming we're working within 252-bit numbers.
})

await circuit.expectPass(INPUT, OUTPUT)
})
})

describe("SafeGreaterThan", () => {
let circuit: WitnessTester<["in"], ["out"]>

it("Should correctly compare two numbers [x, x]", async () => {
// Test values
const inValues = [5, 5] // in[0] === in[1], expecting 'out' to be 0.
const expectedOut = 0 // Since 5 is equal to 5.

const INPUT = {
in: inValues
}

const OUTPUT = {
out: expectedOut
}

circuit = await circomkit.WitnessTester("SafeGreaterThan", {
file: "safe-comparators",
template: "SafeGreaterThan",
params: [252] // Assuming we're working within 252-bit numbers.
})

await circuit.expectPass(INPUT, OUTPUT)
})

it("Should correctly compare two numbers [x-1, x]", async () => {
// Test values
const inValues = [5, 6] // in[0] < in[1], expecting 'out' to be 0.
const expectedOut = 0 // Since 5 is less than 6.

const INPUT = {
in: inValues
}

const OUTPUT = {
out: expectedOut
}

circuit = await circomkit.WitnessTester("SafeGreaterThan", {
file: "safe-comparators",
template: "SafeGreaterThan",
params: [252] // Assuming we're working within 252-bit numbers.
})

await circuit.expectPass(INPUT, OUTPUT)
})

it("Should correctly compare two numbers [x, x-1]", async () => {
// Test values
const inValues = [6, 5] // in[0] > in[1], expecting 'out' to be 1.
const expectedOut = 1 // Since 6 is greater than 5.

const INPUT = {
in: inValues
}

const OUTPUT = {
out: expectedOut
}

circuit = await circomkit.WitnessTester("SafeGreaterThan", {
file: "safe-comparators",
template: "SafeGreaterThan",
params: [252] // Assuming we're working within 252-bit numbers.
})

await circuit.expectPass(INPUT, OUTPUT)
})
})

describe("SafeGreaterEqThan", () => {
let circuit: WitnessTester<["in"], ["out"]>

it("Should correctly compare two numbers [x, x]", async () => {
// Test values
const inValues = [5, 5] // in[0] === in[1], expecting 'out' to be 1.
const expectedOut = 1 // Since 5 is equal to 5.

const INPUT = {
in: inValues
}

const OUTPUT = {
out: expectedOut
}

circuit = await circomkit.WitnessTester("SafeGreaterEqThan", {
file: "safe-comparators",
template: "SafeGreaterEqThan",
params: [252] // Assuming we're working within 252-bit numbers.
})

await circuit.expectPass(INPUT, OUTPUT)
})

it("Should correctly compare two numbers [x-1, x]", async () => {
// Test values
const inValues = [5, 6] // in[0] < in[1], expecting 'out' to be 0.
const expectedOut = 0 // Since 5 is less than 6.

const INPUT = {
in: inValues
}

const OUTPUT = {
out: expectedOut
}

circuit = await circomkit.WitnessTester("SafeGreaterEqThan", {
file: "safe-comparators",
template: "SafeGreaterEqThan",
params: [252] // Assuming we're working within 252-bit numbers.
})

await circuit.expectPass(INPUT, OUTPUT)
})

it("Should correctly compare two numbers [x, x-1]", async () => {
// Test values
const inValues = [6, 5] // in[0] > in[1], expecting 'out' to be 1.
const expectedOut = 1 // Since 6 is greater than 5.

const INPUT = {
in: inValues
}

const OUTPUT = {
out: expectedOut
}

circuit = await circomkit.WitnessTester("SafeGreaterEqThan", {
file: "safe-comparators",
template: "SafeGreaterEqThan",
params: [252] // Assuming we're working within 252-bit numbers.
})

await circuit.expectPass(INPUT, OUTPUT)
})
})
})

0 comments on commit 401a0e5

Please sign in to comment.