chore: implement Gt and GtEq as syntactic sugar (#216)

* Implement Gt and GtEq as syntactic sugar

* Update src/backends/plonky2/circuits/mainpod.rs

Co-authored-by: Eduard S. <eduardsanou@posteo.net>

* Op verification circuit refactor

* Code review

* Add range check to Eq case of LtEq

* Style

* Factor out ValueOf statement argument type checks

* Formatting

* Clean-up

* Safety

* Take sign into account

* Simplify sign check

---------

Co-authored-by: Eduard S. <eduardsanou@posteo.net>
This commit is contained in:
Ahmad Afuni 2025-05-06 06:59:59 +10:00 committed by GitHub
parent e420aa7b32
commit 53ade6ea26
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 451 additions and 170 deletions

View file

@ -60,16 +60,15 @@ pub enum NativeOperation {
CopyStatement = 2,
EqualFromEntries = 3,
NotEqualFromEntries = 4,
GtFromEntries = 5,
LtEqFromEntries = 5,
LtFromEntries = 6,
TransitiveEqualFromStatements = 7,
GtToNotEqual = 8,
LtToNotEqual = 9,
ContainsFromEntries = 10,
NotContainsFromEntries = 11,
SumOf = 13,
ProductOf = 14,
MaxOf = 15,
LtToNotEqual = 8,
ContainsFromEntries = 9,
NotContainsFromEntries = 10,
SumOf = 11,
ProductOf = 12,
MaxOf = 13,
// Syntactic sugar operations. These operations are not supported by the backend. The
// frontend compiler is responsible of translating these operations into the operations above.
@ -78,6 +77,9 @@ pub enum NativeOperation {
SetContainsFromEntries = 1003,
SetNotContainsFromEntries = 1004,
ArrayContainsFromEntries = 1005,
GtEqFromEntries = 1006,
GtFromEntries = 1007,
GtToNotEqual = 1008,
}
impl ToFields for NativeOperation {
@ -102,12 +104,11 @@ impl OperationType {
NativeOperation::NotEqualFromEntries => {
Some(Predicate::Native(NativePredicate::NotEqual))
}
NativeOperation::GtFromEntries => Some(Predicate::Native(NativePredicate::Gt)),
NativeOperation::LtEqFromEntries => Some(Predicate::Native(NativePredicate::LtEq)),
NativeOperation::LtFromEntries => Some(Predicate::Native(NativePredicate::Lt)),
NativeOperation::TransitiveEqualFromStatements => {
Some(Predicate::Native(NativePredicate::Equal))
}
NativeOperation::GtToNotEqual => Some(Predicate::Native(NativePredicate::NotEqual)),
NativeOperation::LtToNotEqual => Some(Predicate::Native(NativePredicate::NotEqual)),
NativeOperation::ContainsFromEntries => {
Some(Predicate::Native(NativePredicate::Contains))
@ -133,10 +134,9 @@ pub enum Operation {
CopyStatement(Statement),
EqualFromEntries(Statement, Statement),
NotEqualFromEntries(Statement, Statement),
GtFromEntries(Statement, Statement),
LtEqFromEntries(Statement, Statement),
LtFromEntries(Statement, Statement),
TransitiveEqualFromStatements(Statement, Statement),
GtToNotEqual(Statement),
LtToNotEqual(Statement),
ContainsFromEntries(
/* root */ Statement,
@ -165,10 +165,9 @@ impl Operation {
Self::CopyStatement(_) => OT::Native(CopyStatement),
Self::EqualFromEntries(_, _) => OT::Native(EqualFromEntries),
Self::NotEqualFromEntries(_, _) => OT::Native(NotEqualFromEntries),
Self::GtFromEntries(_, _) => OT::Native(GtFromEntries),
Self::LtEqFromEntries(_, _) => OT::Native(LtEqFromEntries),
Self::LtFromEntries(_, _) => OT::Native(LtFromEntries),
Self::TransitiveEqualFromStatements(_, _) => OT::Native(TransitiveEqualFromStatements),
Self::GtToNotEqual(_) => OT::Native(GtToNotEqual),
Self::LtToNotEqual(_) => OT::Native(LtToNotEqual),
Self::ContainsFromEntries(_, _, _, _) => OT::Native(ContainsFromEntries),
Self::NotContainsFromEntries(_, _, _) => OT::Native(NotContainsFromEntries),
@ -186,10 +185,9 @@ impl Operation {
Self::CopyStatement(s) => vec![s],
Self::EqualFromEntries(s1, s2) => vec![s1, s2],
Self::NotEqualFromEntries(s1, s2) => vec![s1, s2],
Self::GtFromEntries(s1, s2) => vec![s1, s2],
Self::LtEqFromEntries(s1, s2) => vec![s1, s2],
Self::LtFromEntries(s1, s2) => vec![s1, s2],
Self::TransitiveEqualFromStatements(s1, s2) => vec![s1, s2],
Self::GtToNotEqual(s) => vec![s],
Self::LtToNotEqual(s) => vec![s],
Self::ContainsFromEntries(s1, s2, s3, _pf) => vec![s1, s2, s3],
Self::NotContainsFromEntries(s1, s2, _pf) => vec![s1, s2],
@ -229,8 +227,8 @@ impl Operation {
(NO::NotEqualFromEntries, (Some(s1), Some(s2), None), OA::None, 2) => {
Self::NotEqualFromEntries(s1, s2)
}
(NO::GtFromEntries, (Some(s1), Some(s2), None), OA::None, 2) => {
Self::GtFromEntries(s1, s2)
(NO::LtEqFromEntries, (Some(s1), Some(s2), None), OA::None, 2) => {
Self::LtEqFromEntries(s1, s2)
}
(NO::LtFromEntries, (Some(s1), Some(s2), None), OA::None, 2) => {
Self::LtFromEntries(s1, s2)
@ -282,8 +280,8 @@ impl Operation {
(Self::NotEqualFromEntries(ValueOf(ak1, v1), ValueOf(ak2, v2)), NotEqual(ak3, ak4)) => {
Ok(v1 != v2 && ak3 == ak1 && ak4 == ak2)
}
(Self::GtFromEntries(ValueOf(ak1, v1), ValueOf(ak2, v2)), Gt(ak3, ak4)) => {
Ok(v1 > v2 && ak3 == ak1 && ak4 == ak2)
(Self::LtEqFromEntries(ValueOf(ak1, v1), ValueOf(ak2, v2)), LtEq(ak3, ak4)) => {
Ok(v1 <= v2 && ak3 == ak1 && ak4 == ak2)
}
(Self::LtFromEntries(ValueOf(ak1, v1), ValueOf(ak2, v2)), Lt(ak3, ak4)) => {
Ok(v1 < v2 && ak3 == ak1 && ak4 == ak2)
@ -302,7 +300,6 @@ impl Operation {
Self::TransitiveEqualFromStatements(Equal(ak1, ak2), Equal(ak3, ak4)),
Equal(ak5, ak6),
) => Ok(ak2 == ak3 && ak5 == ak1 && ak6 == ak4),
(Self::GtToNotEqual(Gt(ak1, ak2)), NotEqual(ak3, ak4)) => Ok(ak1 == ak3 && ak2 == ak4),
(Self::LtToNotEqual(Lt(ak1, ak2)), NotEqual(ak3, ak4)) => Ok(ak1 == ak3 && ak2 == ak4),
(
Self::SumOf(ValueOf(ak1, v1), ValueOf(ak2, v2), ValueOf(ak3, v3)),

View file

@ -25,7 +25,7 @@ pub enum NativePredicate {
ValueOf = 1,
Equal = 2,
NotEqual = 3,
Gt = 4,
LtEq = 4,
Lt = 5,
Contains = 6,
NotContains = 7,
@ -40,6 +40,8 @@ pub enum NativePredicate {
SetContains = 1002,
SetNotContains = 1003,
ArrayContains = 1004, // there is no ArrayNotContains
GtEq = 1005,
Gt = 1006,
}
impl ToFields for NativePredicate {
@ -89,7 +91,7 @@ pub enum Statement {
ValueOf(AnchoredKey, Value),
Equal(AnchoredKey, AnchoredKey),
NotEqual(AnchoredKey, AnchoredKey),
Gt(AnchoredKey, AnchoredKey),
LtEq(AnchoredKey, AnchoredKey),
Lt(AnchoredKey, AnchoredKey),
Contains(
/* root */ AnchoredKey,
@ -114,7 +116,7 @@ impl Statement {
Self::ValueOf(_, _) => Native(NativePredicate::ValueOf),
Self::Equal(_, _) => Native(NativePredicate::Equal),
Self::NotEqual(_, _) => Native(NativePredicate::NotEqual),
Self::Gt(_, _) => Native(NativePredicate::Gt),
Self::LtEq(_, _) => Native(NativePredicate::LtEq),
Self::Lt(_, _) => Native(NativePredicate::Lt),
Self::Contains(_, _, _) => Native(NativePredicate::Contains),
Self::NotContains(_, _) => Native(NativePredicate::NotContains),
@ -131,7 +133,7 @@ impl Statement {
Self::ValueOf(ak, v) => vec![Key(ak), Literal(v)],
Self::Equal(ak1, ak2) => vec![Key(ak1), Key(ak2)],
Self::NotEqual(ak1, ak2) => vec![Key(ak1), Key(ak2)],
Self::Gt(ak1, ak2) => vec![Key(ak1), Key(ak2)],
Self::LtEq(ak1, ak2) => vec![Key(ak1), Key(ak2)],
Self::Lt(ak1, ak2) => vec![Key(ak1), Key(ak2)],
Self::Contains(ak1, ak2, ak3) => vec![Key(ak1), Key(ak2), Key(ak3)],
Self::NotContains(ak1, ak2) => vec![Key(ak1), Key(ak2)],
@ -172,11 +174,11 @@ impl Statement {
Err(Error::incorrect_statements_args())
}
}
Native(NativePredicate::Gt) => {
Native(NativePredicate::LtEq) => {
if let (StatementArg::Key(a0), StatementArg::Key(a1)) =
(args[0].clone(), args[1].clone())
{
Ok(Self::Gt(a0, a1))
Ok(Self::LtEq(a0, a1))
} else {
Err(Error::incorrect_statements_args())
}