Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generalize lookups to set inclusion constraints #427

Open
1 of 2 tasks
vlasin opened this issue Jan 6, 2025 · 3 comments · May be fixed by #445
Open
1 of 2 tasks

Generalize lookups to set inclusion constraints #427

vlasin opened this issue Jan 6, 2025 · 3 comments · May be fixed by #445
Assignees

Comments

@vlasin
Copy link
Contributor

vlasin commented Jan 6, 2025

After the discussion in #252, we arrived at the idea that ArithmeticCircuit is an intermediate representation of the computation that should allow an unrestricted ability to create polynomial, lookup, and fold constraints. If a particular proving system (e.g., Plonk) does not support a certain type of constraints, we convert them to the supported form during the protocol setup computation.

Given the above, we want to generalize the current lookup constraints to the inclusion checks:

$$ (x_1, \dots, x_{k}) \in T $$

Translating this to Haskell, we probably want T to be represented by Map and the tuple of variables to be a functor. We do not restrict the number of such sets T to be used in the same ArithmeticCircuit.

  • Refactor ArithmeticCircuit type, replacing acRange field
  • Refactor MonadCircuit and its instances
@TurtlePU
Copy link
Contributor

TurtlePU commented Jan 6, 2025

during the protocol setup computation

Are we sure about this? Conversion will need access to quite low-level circuit APIs, doing this on the compilation stage seemed most reasonable.

Also this would help to keep protocol code dedicated to cryptography stuff only

@vlasin
Copy link
Contributor Author

vlasin commented Jan 6, 2025

Well, I believe the conversion to the proof protocol format is a separate step. The workflow probably should go like this:

  1. Compile the function to the IR of ArithmeticCircuit
  2. Post-compile optimization (as a general rule, we want to optimize as we go, but it might not be always possible)
  3. Convert to a proof protocol format
  4. Protocol-specific optimizations (?)

So, we can wrap all 4 steps in a compile function whose output is a prepared setup of a specific protocol. But we should also have "internal" compile that only produces "ArithmeticCircuit". The latter, for example, is useful in IVC.

@hovanja2011 hovanja2011 linked a pull request Jan 16, 2025 that will close this issue
@TurtlePU
Copy link
Contributor

TurtlePU commented Jan 20, 2025

To fix it in text somewhere: the current problem is that we have to describe $T$ effectively in order to be able to use it as a key in some "acLookup" map.

For compact lookup table descriptions, I propose to use the following GADT:

-- | @LookupTable a f@ is a type of compact lookup table descriptions using ideas from relational algebra.
-- @a@ is a base field type, @f@ is a functor such that @f a@ is a type whose subset this lookup table describes.
data LookupTable a f where
  -- | @Ranges@ describes a set of disjoint intervals on the base field.
  Ranges :: Set (a, a) -> LookupTable a Par1
  -- | @Product t u@ is a cartesian product of tables @t@ and @u@.
  Product :: LookupTable a f -> LookupTable a g -> LookupTable a (f :*: g)
  -- | @Plot f x@ is a plot of a function @f@ with @x@ as a domain.
  Plot :: FunctionId (f a -> g a) -> LookupTable a f -> LookupTable a (f :*: g)

Now, on the topic of function ids. I didn't find any way to easily serialize a Haskell function (maybe @zlonast can help?), so for now I came up with the following addition to the MonadCircuit interface:

class Monad m => MonadCircuit v a w m where
  ...
  registerFunction :: (forall x. ResidueField a x => f x -> g x) -> m (FunctionId (f a -> g a))

This uses the same trick as vertex generation -- choose x to be a MerkleHash and you would get the id which you can use to also store the function inside the circuit.

P.S. Note that if we had some simpler technique to get some kind of function ids / some similar DSL for description of functions, we could let f be just a type instead of a functor.

P.P.S. I mean we could go with foreign function pointers, but I don't know whether this would work ok

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants