Fix range check (#1309)
* fix uint range check * update bit cache with correct bits * suggestions * js fmt * clippy * fix range check, add more tests * update changelog * fieldlt improvements * fix tests
This commit is contained in:
parent
c7e4e29ad0
commit
6c49edc075
32 changed files with 1717 additions and 132 deletions
1
changelogs/unreleased/1309-dark64
Normal file
1
changelogs/unreleased/1309-dark64
Normal file
|
@ -0,0 +1 @@
|
|||
Improve safety in range checks
|
|
@ -18,7 +18,7 @@ pub enum RuntimeError {
|
|||
BranchIsolation,
|
||||
ConstantLtBitness,
|
||||
ConstantLtSum,
|
||||
LtFinalSum,
|
||||
LtSum,
|
||||
LtSymetric,
|
||||
Or,
|
||||
Xor,
|
||||
|
@ -83,7 +83,7 @@ impl fmt::Display for RuntimeError {
|
|||
BranchIsolation => "Branch isolation failed",
|
||||
ConstantLtBitness => "Bitness check failed in constant Lt check",
|
||||
ConstantLtSum => "Sum check failed in constant Lt check",
|
||||
LtFinalSum => "Sum check failed in final Lt check",
|
||||
LtSum => "Sum check failed in Lt check",
|
||||
LtSymetric => "Symetrical check failed in Lt check",
|
||||
Or => "Or check failed",
|
||||
Xor => "Xor check failed",
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -841,7 +841,7 @@ impl<'ast, T: Field> Flattener<'ast, T> {
|
|||
let lhs_id = self.define(lhs_flattened, statements_flattened);
|
||||
let rhs_id = self.define(rhs_flattened, statements_flattened);
|
||||
|
||||
// shifted_sub := 2**safe_width + lhs - rhs
|
||||
// shifted_sub := 2**bit_width + lhs - rhs
|
||||
let shifted_sub = FlatExpression::add(
|
||||
FlatExpression::value(T::from(2).pow(bit_width)),
|
||||
FlatExpression::sub(
|
||||
|
@ -857,7 +857,7 @@ impl<'ast, T: Field> Flattener<'ast, T> {
|
|||
sub_width,
|
||||
sub_width,
|
||||
statements_flattened,
|
||||
RuntimeError::IncompleteDynamicRange,
|
||||
RuntimeError::Sum,
|
||||
);
|
||||
|
||||
FlatExpression::sub(
|
||||
|
@ -898,19 +898,42 @@ impl<'ast, T: Field> Flattener<'ast, T> {
|
|||
.flatten_select_expression(statements_flattened, e)
|
||||
.get_field_unchecked(),
|
||||
BooleanExpression::FieldLt(e) => {
|
||||
// Get the bit width to know the size of the binary decompositions for this Field
|
||||
let bit_width = T::get_required_bits();
|
||||
|
||||
let safe_width = bit_width - 2; // dynamic comparison is not complete, it only applies to field elements whose difference is strictly smaller than 2**(bitwidth - 2)
|
||||
|
||||
let lhs_flattened = self.flatten_field_expression(statements_flattened, *e.left);
|
||||
let rhs_flattened = self.flatten_field_expression(statements_flattened, *e.right);
|
||||
self.lt_check(
|
||||
statements_flattened,
|
||||
lhs_flattened,
|
||||
rhs_flattened,
|
||||
safe_width,
|
||||
)
|
||||
|
||||
match (lhs_flattened, rhs_flattened) {
|
||||
(e, FlatExpression::Value(c)) => {
|
||||
self.constant_lt_check(statements_flattened, e, c.value)
|
||||
}
|
||||
(FlatExpression::Value(c), e) => self.constant_lt_check(
|
||||
statements_flattened,
|
||||
FlatExpression::sub(T::max_value().into(), e),
|
||||
T::max_value() - c.value,
|
||||
),
|
||||
(lhs, rhs) => {
|
||||
// Get the bit width to know the size of the binary decompositions for this Field
|
||||
let bit_width = T::get_required_bits();
|
||||
let safe_width = bit_width - 2; // dynamic comparison is not complete, it only applies to field elements whose difference is strictly smaller than 2**(bitwidth - 2)
|
||||
let safe_max = T::from(2).pow(safe_width);
|
||||
|
||||
// enforce that lhs and rhs are in the correct range
|
||||
self.enforce_constant_lt_check(
|
||||
statements_flattened,
|
||||
lhs.clone(),
|
||||
safe_max,
|
||||
RuntimeError::IncompleteDynamicRange,
|
||||
);
|
||||
|
||||
self.enforce_constant_lt_check(
|
||||
statements_flattened,
|
||||
rhs.clone(),
|
||||
safe_max,
|
||||
RuntimeError::IncompleteDynamicRange,
|
||||
);
|
||||
|
||||
self.lt_check(statements_flattened, lhs, rhs, safe_width)
|
||||
}
|
||||
}
|
||||
}
|
||||
BooleanExpression::BoolEq(e) => {
|
||||
// lhs and rhs are booleans, they flatten to 0 or 1
|
||||
|
@ -1980,7 +2003,8 @@ impl<'ast, T: Field> Flattener<'ast, T> {
|
|||
///
|
||||
/// # Notes
|
||||
/// * `from` and `to` must be smaller or equal to `T::get_required_bits()`, the bitwidth of the prime field
|
||||
/// * the result is not checked to be in range. This is fine for `to < T::get_required_bits()`, but otherwise it is the caller's responsibility to add that check
|
||||
/// * The result is not checked to be in range unless the bits of the expression were already decomposed with a higher bitwidth than `to`
|
||||
/// * This is fine for `to < T::get_required_bits()`, but otherwise it is the caller's responsibility to add that check
|
||||
fn get_bits_unchecked(
|
||||
&mut self,
|
||||
e: &FlatUExpression<T>,
|
||||
|
@ -2015,19 +2039,30 @@ impl<'ast, T: Field> Flattener<'ast, T> {
|
|||
let from = std::cmp::max(from, to);
|
||||
let res = match self.bits_cache.entry(e.field.clone().unwrap()) {
|
||||
Entry::Occupied(entry) => {
|
||||
let res: Vec<_> = entry.get().clone();
|
||||
// if we already know a decomposition, its number of elements has to be smaller or equal to `to`
|
||||
let mut res: Vec<_> = entry.get().clone();
|
||||
|
||||
// only keep the last `to` values and return the sum of the others
|
||||
let sum = res
|
||||
.drain(0..res.len().saturating_sub(to))
|
||||
.fold(FlatExpression::from(T::zero()), |acc, e| {
|
||||
FlatExpression::add(acc, e)
|
||||
});
|
||||
|
||||
// force the sum to be 0
|
||||
statements_flattened.push_back(FlatStatement::condition(
|
||||
FlatExpression::value(T::from(0)),
|
||||
sum,
|
||||
error,
|
||||
));
|
||||
|
||||
// sanity check that we have at most `to` values
|
||||
assert!(res.len() <= to);
|
||||
|
||||
// we then pad it with zeroes on the left (big endian) to return `to` bits
|
||||
if res.len() == to {
|
||||
res
|
||||
} else {
|
||||
(0..to - res.len())
|
||||
.map(|_| FlatExpression::value(T::zero()))
|
||||
.chain(res)
|
||||
.collect()
|
||||
}
|
||||
// return the result left-padded to `to` values
|
||||
std::iter::repeat(FlatExpression::value(T::zero()))
|
||||
.take(to - res.len())
|
||||
.chain(res.clone())
|
||||
.collect()
|
||||
}
|
||||
Entry::Vacant(_) => {
|
||||
let bits = (0..from).map(|_| self.use_sym()).collect::<Vec<_>>();
|
||||
|
@ -2553,7 +2588,23 @@ impl<'ast, T: Field> Flattener<'ast, T> {
|
|||
),
|
||||
(lhs, rhs) => {
|
||||
let bit_width = T::get_required_bits();
|
||||
let safe_width = bit_width - 2; // dynamic comparison is not complete
|
||||
let safe_width = bit_width - 2; // dynamic comparison is not complete, it only applies to field elements whose difference is strictly smaller than 2**(bitwidth - 2)
|
||||
let safe_max = T::from(2).pow(safe_width);
|
||||
|
||||
self.enforce_constant_lt_check(
|
||||
statements_flattened,
|
||||
lhs.clone(),
|
||||
safe_max,
|
||||
RuntimeError::IncompleteDynamicRange,
|
||||
);
|
||||
|
||||
self.enforce_constant_lt_check(
|
||||
statements_flattened,
|
||||
rhs.clone(),
|
||||
safe_max,
|
||||
RuntimeError::IncompleteDynamicRange,
|
||||
);
|
||||
|
||||
let e = self.lt_check(statements_flattened, lhs, rhs, safe_width);
|
||||
statements_flattened.push_back(FlatStatement::condition(
|
||||
e,
|
||||
|
@ -2583,7 +2634,23 @@ impl<'ast, T: Field> Flattener<'ast, T> {
|
|||
),
|
||||
(lhs, rhs) => {
|
||||
let bit_width = T::get_required_bits();
|
||||
let safe_width = bit_width - 2; // dynamic comparison is not complete
|
||||
let safe_width = bit_width - 2; // dynamic comparison is not complete, it only applies to field elements whose difference is strictly smaller than 2**(bitwidth - 2)
|
||||
|
||||
let safe_max = T::from(2).pow(safe_width);
|
||||
self.enforce_constant_lt_check(
|
||||
statements_flattened,
|
||||
lhs.clone(),
|
||||
safe_max,
|
||||
RuntimeError::IncompleteDynamicRange,
|
||||
);
|
||||
|
||||
self.enforce_constant_lt_check(
|
||||
statements_flattened,
|
||||
rhs.clone(),
|
||||
safe_max,
|
||||
RuntimeError::IncompleteDynamicRange,
|
||||
);
|
||||
|
||||
let e = self.le_check(statements_flattened, lhs, rhs, safe_width);
|
||||
statements_flattened.push_back(FlatStatement::condition(
|
||||
e,
|
||||
|
@ -2593,10 +2660,49 @@ impl<'ast, T: Field> Flattener<'ast, T> {
|
|||
}
|
||||
}
|
||||
}
|
||||
BooleanExpression::UintLe(e) => {
|
||||
BooleanExpression::UintLt(e) => {
|
||||
let bitwidth = e.left.bitwidth as usize;
|
||||
let lhs = self
|
||||
.flatten_uint_expression(statements_flattened, *e.left)
|
||||
.get_field_unchecked();
|
||||
|
||||
let rhs = self
|
||||
.flatten_uint_expression(statements_flattened, *e.right)
|
||||
.get_field_unchecked();
|
||||
|
||||
match (lhs, rhs) {
|
||||
(e, FlatExpression::Value(c)) => self.enforce_constant_lt_check(
|
||||
statements_flattened,
|
||||
e,
|
||||
c.value,
|
||||
error.into(),
|
||||
),
|
||||
// c < e <=> 2^bw - 1 - e < 2^bw - 1 - c
|
||||
(FlatExpression::Value(c), e) => {
|
||||
let max = T::from(2u32).pow(bitwidth) - T::one();
|
||||
self.enforce_constant_lt_check(
|
||||
statements_flattened,
|
||||
FlatExpression::sub(max.into(), e),
|
||||
max - c.value,
|
||||
error.into(),
|
||||
)
|
||||
}
|
||||
(lhs, rhs) => {
|
||||
let e = self.lt_check(statements_flattened, lhs, rhs, bitwidth);
|
||||
statements_flattened.push_back(FlatStatement::condition(
|
||||
e,
|
||||
FlatExpression::value(T::one()),
|
||||
error.into(),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
BooleanExpression::UintLe(e) => {
|
||||
let bitwidth = e.left.bitwidth as usize;
|
||||
let lhs = self
|
||||
.flatten_uint_expression(statements_flattened, *e.left)
|
||||
.get_field_unchecked();
|
||||
|
||||
let rhs = self
|
||||
.flatten_uint_expression(statements_flattened, *e.right)
|
||||
.get_field_unchecked();
|
||||
|
@ -2608,17 +2714,18 @@ impl<'ast, T: Field> Flattener<'ast, T> {
|
|||
c.value,
|
||||
error.into(),
|
||||
),
|
||||
// c <= e <=> p - 1 - e <= p - 1 - c
|
||||
(FlatExpression::Value(c), e) => self.enforce_constant_le_check(
|
||||
statements_flattened,
|
||||
FlatExpression::sub(T::max_value().into(), e),
|
||||
T::max_value() - c.value,
|
||||
error.into(),
|
||||
),
|
||||
// c <= e <=> 2^bw - 1 - e <= 2^bw - 1 - c
|
||||
(FlatExpression::Value(c), e) => {
|
||||
let max = T::from(2u32).pow(bitwidth) - T::one();
|
||||
self.enforce_constant_le_check(
|
||||
statements_flattened,
|
||||
FlatExpression::sub(max.into(), e),
|
||||
max - c.value,
|
||||
error.into(),
|
||||
)
|
||||
}
|
||||
(lhs, rhs) => {
|
||||
let bit_width = T::get_required_bits();
|
||||
let safe_width = bit_width - 2; // dynamic comparison is not complete
|
||||
let e = self.le_check(statements_flattened, lhs, rhs, safe_width);
|
||||
let e = self.le_check(statements_flattened, lhs, rhs, bitwidth);
|
||||
statements_flattened.push_back(FlatStatement::condition(
|
||||
e,
|
||||
FlatExpression::value(T::one()),
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
{
|
||||
"entry_point": "./tests/tests/compare_min_to_max.zok",
|
||||
"curves": ["Bn128", "Bls12_381", "Bls12_377", "Bw6_761"],
|
||||
"tests": [
|
||||
{
|
||||
"input": {
|
||||
"values": ["0"]
|
||||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"value": false
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
from "field" import FIELD_MAX;
|
||||
|
||||
// /!\ should be called with a = 0
|
||||
// as `|a - FIELD_MAX| < 2**(N-2)` the comparison should succeed
|
||||
|
||||
def main(field a) -> bool {
|
||||
field p = FIELD_MAX + a;
|
||||
// we added a = 0 to prevent the condition to be evaluated at compile time
|
||||
return a < p;
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
{
|
||||
"entry_point": "./tests/tests/range_check/assert_ge_big_constant.zok",
|
||||
"max_constraint_count": 2,
|
||||
"curves": ["Bn128"],
|
||||
"tests": [
|
||||
{
|
||||
"input": {
|
||||
"values": ["0"]
|
||||
},
|
||||
"output": {
|
||||
"Err": {
|
||||
"UnsatisfiedConstraint": {
|
||||
"error": {
|
||||
"SourceAssertion": {
|
||||
"file": "./tests/tests/range_check/assert_ge_big_constant.zok",
|
||||
"position": {
|
||||
"line": 4,
|
||||
"col": 5
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"input": {
|
||||
"values": [
|
||||
"21888242871839275222246405745257275088548364400416034343698204186575808495614"
|
||||
]
|
||||
},
|
||||
"output": {
|
||||
"Err": {
|
||||
"UnsatisfiedConstraint": {
|
||||
"error": {
|
||||
"SourceAssertion": {
|
||||
"file": "./tests/tests/range_check/assert_ge_big_constant.zok",
|
||||
"position": {
|
||||
"line": 4,
|
||||
"col": 5
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"input": {
|
||||
"values": [
|
||||
"21888242871839275222246405745257275088548364400416034343698204186575808495615"
|
||||
]
|
||||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"value": []
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"input": {
|
||||
"values": [
|
||||
"21888242871839275222246405745257275088548364400416034343698204186575808495616"
|
||||
]
|
||||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"value": []
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
from "field" import FIELD_MAX;
|
||||
|
||||
def main(field x) {
|
||||
assert(x >= FIELD_MAX - 1);
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"entry_point": "./tests/tests/range_check/assert_ge.zok",
|
||||
"entry_point": "./tests/tests/range_check/assert_ge_constant.zok",
|
||||
"max_constraint_count": 509,
|
||||
"curves": ["Bn128"],
|
||||
"tests": [
|
||||
|
@ -12,7 +12,7 @@
|
|||
"UnsatisfiedConstraint": {
|
||||
"error": {
|
||||
"SourceAssertion": {
|
||||
"file": "./tests/tests/range_check/assert_ge.zok",
|
||||
"file": "./tests/tests/range_check/assert_ge_constant.zok",
|
||||
"position": {
|
||||
"line": 2,
|
||||
"col": 5
|
||||
|
@ -32,7 +32,7 @@
|
|||
"UnsatisfiedConstraint": {
|
||||
"error": {
|
||||
"SourceAssertion": {
|
||||
"file": "./tests/tests/range_check/assert_ge.zok",
|
||||
"file": "./tests/tests/range_check/assert_ge_constant.zok",
|
||||
"position": {
|
||||
"line": 2,
|
||||
"col": 5
|
|
@ -1,4 +1,3 @@
|
|||
def main(field x) {
|
||||
assert(x >= 2);
|
||||
return;
|
||||
}
|
|
@ -2,5 +2,4 @@ from "field" import FIELD_MAX;
|
|||
|
||||
def main(field x) {
|
||||
assert(x > FIELD_MAX - 1);
|
||||
return;
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"entry_point": "./tests/tests/range_check/assert_gt.zok",
|
||||
"entry_point": "./tests/tests/range_check/assert_gt_constant.zok",
|
||||
"max_constraint_count": 508,
|
||||
"curves": ["Bn128"],
|
||||
"tests": [
|
||||
|
@ -12,7 +12,7 @@
|
|||
"UnsatisfiedConstraint": {
|
||||
"error": {
|
||||
"SourceAssertion": {
|
||||
"file": "./tests/tests/range_check/assert_gt.zok",
|
||||
"file": "./tests/tests/range_check/assert_gt_constant.zok",
|
||||
"position": {
|
||||
"line": 2,
|
||||
"col": 5
|
||||
|
@ -32,7 +32,7 @@
|
|||
"UnsatisfiedConstraint": {
|
||||
"error": {
|
||||
"SourceAssertion": {
|
||||
"file": "./tests/tests/range_check/assert_gt.zok",
|
||||
"file": "./tests/tests/range_check/assert_gt_constant.zok",
|
||||
"position": {
|
||||
"line": 2,
|
||||
"col": 5
|
||||
|
@ -52,7 +52,7 @@
|
|||
"UnsatisfiedConstraint": {
|
||||
"error": {
|
||||
"SourceAssertion": {
|
||||
"file": "./tests/tests/range_check/assert_gt.zok",
|
||||
"file": "./tests/tests/range_check/assert_gt_constant.zok",
|
||||
"position": {
|
||||
"line": 2,
|
||||
"col": 5
|
|
@ -1,4 +1,3 @@
|
|||
def main(field x) {
|
||||
assert(x > 2);
|
||||
return;
|
||||
}
|
|
@ -1,11 +1,11 @@
|
|||
{
|
||||
"entry_point": "./tests/tests/range_check/assert_le.zok",
|
||||
"max_constraint_count": 5,
|
||||
"max_constraint_count": 763,
|
||||
"curves": ["Bn128"],
|
||||
"tests": [
|
||||
{
|
||||
"input": {
|
||||
"values": ["1"]
|
||||
"values": ["1", "2"]
|
||||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
|
@ -15,7 +15,7 @@
|
|||
},
|
||||
{
|
||||
"input": {
|
||||
"values": ["2"]
|
||||
"values": ["2", "2"]
|
||||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
|
@ -25,7 +25,23 @@
|
|||
},
|
||||
{
|
||||
"input": {
|
||||
"values": ["3"]
|
||||
"values": [
|
||||
"1",
|
||||
"7237005577332262213973186563042994240829374041602535252466099000494570602495"
|
||||
]
|
||||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"value": []
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"input": {
|
||||
"values": [
|
||||
"7237005577332262213973186563042994240829374041602535252466099000494570602495",
|
||||
"1"
|
||||
]
|
||||
},
|
||||
"output": {
|
||||
"Err": {
|
||||
|
@ -45,20 +61,30 @@
|
|||
},
|
||||
{
|
||||
"input": {
|
||||
"values": ["15"]
|
||||
"values": [
|
||||
"1",
|
||||
"7237005577332262213973186563042994240829374041602535252466099000494570602496"
|
||||
]
|
||||
},
|
||||
"output": {
|
||||
"Err": {
|
||||
"UnsatisfiedConstraint": {
|
||||
"error": {
|
||||
"SourceAssertion": {
|
||||
"file": "./tests/tests/range_check/assert_le.zok",
|
||||
"position": {
|
||||
"line": 2,
|
||||
"col": 5
|
||||
}
|
||||
}
|
||||
}
|
||||
"error": "IncompleteDynamicRange"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"input": {
|
||||
"values": [
|
||||
"7237005577332262213973186563042994240829374041602535252466099000494570602496",
|
||||
"1"
|
||||
]
|
||||
},
|
||||
"output": {
|
||||
"Err": {
|
||||
"UnsatisfiedConstraint": {
|
||||
"error": "IncompleteDynamicRange"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
def main(field x) {
|
||||
assert(x <= 2);
|
||||
return;
|
||||
def main(field a, field b) {
|
||||
assert(a <= b);
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
{
|
||||
"entry_point": "./tests/tests/range_check/assert_le_big_constant.zok",
|
||||
"max_constraint_count": 508,
|
||||
"curves": ["Bn128"],
|
||||
"tests": [
|
||||
{
|
||||
"input": {
|
||||
"values": ["0"]
|
||||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"value": []
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"input": {
|
||||
"values": [
|
||||
"21888242871839275222246405745257275088548364400416034343698204186575808495614"
|
||||
]
|
||||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"value": []
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"input": {
|
||||
"values": [
|
||||
"21888242871839275222246405745257275088548364400416034343698204186575808495615"
|
||||
]
|
||||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"value": []
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"input": {
|
||||
"values": [
|
||||
"21888242871839275222246405745257275088548364400416034343698204186575808495616"
|
||||
]
|
||||
},
|
||||
"output": {
|
||||
"Err": {
|
||||
"UnsatisfiedConstraint": {
|
||||
"error": {
|
||||
"SourceAssertion": {
|
||||
"file": "./tests/tests/range_check/assert_le_big_constant.zok",
|
||||
"position": {
|
||||
"line": 4,
|
||||
"col": 5
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
from "field" import FIELD_MAX;
|
||||
|
||||
def main(field x) {
|
||||
assert(x <= FIELD_MAX - 1);
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
{
|
||||
"entry_point": "./tests/tests/range_check/assert_le_constant.zok",
|
||||
"max_constraint_count": 5,
|
||||
"curves": ["Bn128"],
|
||||
"tests": [
|
||||
{
|
||||
"input": {
|
||||
"values": ["1"]
|
||||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"value": []
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"input": {
|
||||
"values": ["2"]
|
||||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"value": []
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"input": {
|
||||
"values": ["3"]
|
||||
},
|
||||
"output": {
|
||||
"Err": {
|
||||
"UnsatisfiedConstraint": {
|
||||
"error": {
|
||||
"SourceAssertion": {
|
||||
"file": "./tests/tests/range_check/assert_le_constant.zok",
|
||||
"position": {
|
||||
"line": 2,
|
||||
"col": 5
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"input": {
|
||||
"values": ["15"]
|
||||
},
|
||||
"output": {
|
||||
"Err": {
|
||||
"UnsatisfiedConstraint": {
|
||||
"error": {
|
||||
"SourceAssertion": {
|
||||
"file": "./tests/tests/range_check/assert_le_constant.zok",
|
||||
"position": {
|
||||
"line": 2,
|
||||
"col": 5
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
def main(field x) {
|
||||
assert(x <= 2);
|
||||
}
|
47
zokrates_core_test/tests/tests/range_check/assert_le_u8.json
Normal file
47
zokrates_core_test/tests/tests/range_check/assert_le_u8.json
Normal file
|
@ -0,0 +1,47 @@
|
|||
{
|
||||
"entry_point": "./tests/tests/range_check/assert_le_u8.zok",
|
||||
"max_constraint_count": 31,
|
||||
"curves": ["Bn128"],
|
||||
"tests": [
|
||||
{
|
||||
"input": {
|
||||
"values": ["0x01", "0x02"]
|
||||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"value": []
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"input": {
|
||||
"values": ["0x02", "0x02"]
|
||||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"value": []
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"input": {
|
||||
"values": ["0x04", "0x02"]
|
||||
},
|
||||
"output": {
|
||||
"Err": {
|
||||
"UnsatisfiedConstraint": {
|
||||
"error": {
|
||||
"SourceAssertion": {
|
||||
"file": "./tests/tests/range_check/assert_le_u8.zok",
|
||||
"position": {
|
||||
"line": 2,
|
||||
"col": 5
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
def main(u8 a, u8 b) {
|
||||
assert(a <= b);
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
{
|
||||
"entry_point": "./tests/tests/range_check/assert_le_u8_constant.zok",
|
||||
"max_constraint_count": 12,
|
||||
"curves": ["Bn128"],
|
||||
"tests": [
|
||||
{
|
||||
"input": {
|
||||
"values": ["0x00"]
|
||||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"value": []
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"input": {
|
||||
"values": ["0x01"]
|
||||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"value": []
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"input": {
|
||||
"values": ["0x02"]
|
||||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"value": []
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"input": {
|
||||
"values": ["0x0f"]
|
||||
},
|
||||
"output": {
|
||||
"Err": {
|
||||
"UnsatisfiedConstraint": {
|
||||
"error": {
|
||||
"SourceAssertion": {
|
||||
"file": "./tests/tests/range_check/assert_le_u8_constant.zok",
|
||||
"position": {
|
||||
"line": 2,
|
||||
"col": 5
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
def main(u8 x) {
|
||||
assert(x <= 2);
|
||||
}
|
|
@ -1,11 +1,11 @@
|
|||
{
|
||||
"entry_point": "./tests/tests/range_check/assert_lt.zok",
|
||||
"max_constraint_count": 4,
|
||||
"max_constraint_count": 764,
|
||||
"curves": ["Bn128"],
|
||||
"tests": [
|
||||
{
|
||||
"input": {
|
||||
"values": ["0"]
|
||||
"values": ["1", "2"]
|
||||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
|
@ -15,7 +15,10 @@
|
|||
},
|
||||
{
|
||||
"input": {
|
||||
"values": ["1"]
|
||||
"values": [
|
||||
"1",
|
||||
"7237005577332262213973186563042994240829374041602535252466099000494570602495"
|
||||
]
|
||||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
|
@ -25,7 +28,10 @@
|
|||
},
|
||||
{
|
||||
"input": {
|
||||
"values": ["2"]
|
||||
"values": [
|
||||
"7237005577332262213973186563042994240829374041602535252466099000494570602495",
|
||||
"1"
|
||||
]
|
||||
},
|
||||
"output": {
|
||||
"Err": {
|
||||
|
@ -45,20 +51,30 @@
|
|||
},
|
||||
{
|
||||
"input": {
|
||||
"values": ["15"]
|
||||
"values": [
|
||||
"1",
|
||||
"7237005577332262213973186563042994240829374041602535252466099000494570602496"
|
||||
]
|
||||
},
|
||||
"output": {
|
||||
"Err": {
|
||||
"UnsatisfiedConstraint": {
|
||||
"error": {
|
||||
"SourceAssertion": {
|
||||
"file": "./tests/tests/range_check/assert_lt.zok",
|
||||
"position": {
|
||||
"line": 2,
|
||||
"col": 5
|
||||
}
|
||||
}
|
||||
}
|
||||
"error": "IncompleteDynamicRange"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"input": {
|
||||
"values": [
|
||||
"7237005577332262213973186563042994240829374041602535252466099000494570602496",
|
||||
"1"
|
||||
]
|
||||
},
|
||||
"output": {
|
||||
"Err": {
|
||||
"UnsatisfiedConstraint": {
|
||||
"error": "IncompleteDynamicRange"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
def main(field x) {
|
||||
assert(x < 2);
|
||||
return;
|
||||
def main(field a, field b) {
|
||||
assert(a < b);
|
||||
}
|
|
@ -2,5 +2,4 @@ from "field" import FIELD_MAX;
|
|||
|
||||
def main(field x) {
|
||||
assert(x < FIELD_MAX - 1);
|
||||
return;
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
{
|
||||
"entry_point": "./tests/tests/range_check/assert_lt_constant.zok",
|
||||
"max_constraint_count": 4,
|
||||
"curves": ["Bn128"],
|
||||
"tests": [
|
||||
{
|
||||
"input": {
|
||||
"values": ["0"]
|
||||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"value": []
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"input": {
|
||||
"values": ["1"]
|
||||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"value": []
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"input": {
|
||||
"values": ["2"]
|
||||
},
|
||||
"output": {
|
||||
"Err": {
|
||||
"UnsatisfiedConstraint": {
|
||||
"error": {
|
||||
"SourceAssertion": {
|
||||
"file": "./tests/tests/range_check/assert_lt_constant.zok",
|
||||
"position": {
|
||||
"line": 2,
|
||||
"col": 5
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"input": {
|
||||
"values": ["15"]
|
||||
},
|
||||
"output": {
|
||||
"Err": {
|
||||
"UnsatisfiedConstraint": {
|
||||
"error": {
|
||||
"SourceAssertion": {
|
||||
"file": "./tests/tests/range_check/assert_lt_constant.zok",
|
||||
"position": {
|
||||
"line": 2,
|
||||
"col": 5
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
def main(field x) {
|
||||
assert(x < 2);
|
||||
}
|
|
@ -1,11 +1,11 @@
|
|||
{
|
||||
"entry_point": "./tests/tests/range_check/assert_lt_u8.zok",
|
||||
"max_constraint_count": 9,
|
||||
"max_constraint_count": 29,
|
||||
"curves": ["Bn128"],
|
||||
"tests": [
|
||||
{
|
||||
"input": {
|
||||
"values": ["0x00"]
|
||||
"values": ["0x01", "0x02"]
|
||||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
|
@ -15,17 +15,7 @@
|
|||
},
|
||||
{
|
||||
"input": {
|
||||
"values": ["0x01"]
|
||||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"value": []
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"input": {
|
||||
"values": ["0x02"]
|
||||
"values": ["0x02", "0x02"]
|
||||
},
|
||||
"output": {
|
||||
"Err": {
|
||||
|
@ -45,7 +35,7 @@
|
|||
},
|
||||
{
|
||||
"input": {
|
||||
"values": ["0x0f"]
|
||||
"values": ["0x04", "0x02"]
|
||||
},
|
||||
"output": {
|
||||
"Err": {
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
def main(field x) {
|
||||
assert(x < 2);
|
||||
return;
|
||||
def main(u8 a, u8 b) {
|
||||
assert(a < b);
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
{
|
||||
"entry_point": "./tests/tests/range_check/assert_lt_u8_constant.zok",
|
||||
"max_constraint_count": 10,
|
||||
"curves": ["Bn128"],
|
||||
"tests": [
|
||||
{
|
||||
"input": {
|
||||
"values": ["0x00"]
|
||||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"value": []
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"input": {
|
||||
"values": ["0x01"]
|
||||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"value": []
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"input": {
|
||||
"values": ["0x02"]
|
||||
},
|
||||
"output": {
|
||||
"Err": {
|
||||
"UnsatisfiedConstraint": {
|
||||
"error": {
|
||||
"SourceAssertion": {
|
||||
"file": "./tests/tests/range_check/assert_lt_u8_constant.zok",
|
||||
"position": {
|
||||
"line": 2,
|
||||
"col": 5
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"input": {
|
||||
"values": ["0x0f"]
|
||||
},
|
||||
"output": {
|
||||
"Err": {
|
||||
"UnsatisfiedConstraint": {
|
||||
"error": {
|
||||
"SourceAssertion": {
|
||||
"file": "./tests/tests/range_check/assert_lt_u8_constant.zok",
|
||||
"position": {
|
||||
"line": 2,
|
||||
"col": 5
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
def main(u8 x) {
|
||||
assert(x < 2);
|
||||
}
|
Loading…
Reference in a new issue