GithubHelp home page GithubHelp logo

Comments (4)

HarryR avatar HarryR commented on July 17, 2024

There is a programming style that could be used with Ethsnarks to make implementation easier:

auto m = pb.module("example");
const auto sig = m( EdDSA_Signature() );
auto verify = m( PureEdDSA_Verify(sig) );

But you need separate functions for defining the circuit and generating the witness, e.g.:

sig.witness(...);

I am using a declarative programming style for defining circuits, where it's split into 4 sections:

  • define types
  • construct functions and variables (hooking arguments together etc.)
  • emit constraints
  • generate witness from data

Adding each gadget to a list could avoid needing a generate_r1cs_constraints() function for every instance - only the bas implementation which iterates through the gadgets in the group.

For example:

struct GadgetT {
   ProtoboardT &pb;
};
struct MyGadget : public GadgetT {
    EdDSA_Signature sig{pb};
    PureEdDSA_Verify verify {sig};
};

ProtoboardT pb;
MyGadget gadget{.pb = pb};

The assumption is that this is a more efficient way of passing the .pb member through, and uses explicit ordering of the default initialisations of fields to allow the construction of more complex gadgets. The problem is - what happens when no ProtoboardT parameter is passed?

Encoding to/from json automatically would be a good feature, reducing the need to create custom serialisation functions for each type, e.g. using https://github.com/xyz347/x2struct or Qt slots would make the 'witness' phase easier as fields could be filled with their appropriate values from an arbitrary dictionary.

from ethsnarks.

HarryR avatar HarryR commented on July 17, 2024

Encoding to/from json automatically would be a good feature, reducing the need to create custom serialisation functions for each type, e.g. using https://github.com/xyz347/x2struct or Qt slots would make the 'witness' phase easier as fields could be filled with their appropriate values from an arbitrary dictionary.

The BOOST_FUSION_ADAPT_STRUCT macro can be used to make the names and types of struct members available introspectively, for example: http://andres.senac.es/2011/04/generic-json-serializer.html

Witness data could be passed as a JSON dictionary or boost property tree and converted into the correct types with error checking before setting the value of variables used by the circuit. Only fields which need to be supplied by the user are required.

from ethsnarks.

HarryR avatar HarryR commented on July 17, 2024

Going to avoid using Boost, as it's a huge dependency and makes it difficult to build for WASM, iOS, Android etc.

There are some things which could be easier:


Handling Variables and Linear Combinations

  • Getting value of variable or variables
  • Getting value of linear combination, or array of linear combinations

These can be addressed in several ways:

  1. Add .val(pb) method to VariableT, in addition to pb.val(var)
  2. Add .vals(pb) method to VariableArrayT
  3. Add pb.vals(vars) method to ProtoboardT

Allow the above methods to accept VariableT, VariableArrayT, linear combination and an array of linear combinations.


Make constraints easier to add

When in debug mode, all constraints require an annotation, when in DEBUG mode protoboard will assert when variable has no annotation. Are annotations really 100% necessary (although, they do make debugging easier).

add_r1cs_constraint is a bad method name, this should be much simpler, for example:

pb << ConstraintT(a, b, c, "annotation");

Is much nicer than:

pb.add_r1cs_constraint(ConstraintT(a, b, c), "annotation");

Alternatively, it may be possible to do stuff like:

pb.enforce({
  a * b == c,
  d * e == f
}, "annotation");

Where a*b is a quadratic relation if both A and B are variable. Multiplying a linear combination or variable with another variable or non-constant linear combination would result in a QuadraticRelation (is QuadraticRelation and appropriate term?).

The equality operator overload on QuadraticRelation would result in a ConstraintT, which can then be added to the constraint system

The idea being that we should be able to automatically emit constraints for more complex relationships in a predictable manner.


Make matrix operations easier to perform

Say you have a matrix[t][t], and variables[t]

You want to perform a matrix vector product of matrix * variables to get a result of length [t].

It should be trivial to perform this without writing for loops.

Including generating the witness, and the constraints


Same piece of code, multiple modes (evaluate, constraint, both)

To make it easier to write code, instead of having to produce essentially 3 pieces of code:

  1. Setup the structure / variables etc.
  2. Explicitly fill-in the witnesses for variables, calculate results etc.
  3. Add constraints which enforce the system etc.

We should be able to have one piece of code which does all three, possibly using templates to enable witness/constrain/both, where the result in 'witness mode' will be actual values, but in 'constrain mode' they will be variables.

from ethsnarks.

HarryR avatar HarryR commented on July 17, 2024

Things which need to be easily supported, but to be implemented cleanly would require us to extend libsnark

Interface improvements:

  • Arrays of variables
  • Slices of arrays of variables
  • Initialise and set array from bits & bytes
  • retrieve array as bytes
  • convert bytes to FieldT (big & little-endian)
  • convert bitvector to bytes (big & little endian)
  • merge make_variable into VariableT constructor

This should get rid of everything from "utils.hpp"

General improvements:

  • linear combinations
  • arrays of linear combinations
  • no need for 'evaluating' linear combinations and caching their result
  • matrix operations between arrays of linear combinations and arrays of variables
  • == operation emits constraints (which must be added to context)
  • Const classes & arguments
  • Only evaluate (without generating constraints), or only generating constraints
  • Transparent running, make it look like procedural code

Bitness:

When a variable is declared to be a Bit, it should have an automatic bitness constraint added.
Functions which output bits means the type can be 'Implicitly binary' - meaning it doesn't need a constraint of its own.

A global bitmap is kept with all of the 'bit variables', then the constraints are added at the end.

from ethsnarks.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.