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

R1CS: Add constraints_len, deferred_constraints_len and total_constraints_len #322

Merged
merged 2 commits into from
May 26, 2020

Conversation

rubdos
Copy link
Contributor

@rubdos rubdos commented May 14, 2020

Add methods to count the different kinds of constraints, which comes in handy when developing and benchmarking larger circuits. This is analogue with #284, ConstraintSystem::multipliers_len().

@@ -69,6 +69,17 @@ pub trait ConstraintSystem {
/// Counts the amount of allocated multipliers.
fn multipliers_len(&self) -> usize;

/// Counts the amount of first-phase constraints in the circuit.
fn constraints_len(&self) -> usize;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To my taste, i'd leave this generic sounding name for all the constraints, not just the first phase. If it's important to distinguish between first phase/second phase, I'd have specific methods for them.

Also: it may be useful to just have one method stats() -> Stats that returns a non-exhaustive struct (with private PhantomData or smth like that?) that contains .multipliers: usize, .constraints: usize, first_phase_constraints: usize, .second_phase_constraints: usize etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack on the naming, I'll swap that out.

The most valuable thing about such a Stats struct would be its (derived) Debug implementation. On the other hand, these methods are not really to be "used in production" anyway, so having a separate struct may be a tid of overengineering...

Anyhow, your pick, let me know what you prefer!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For debugging it seems to be more useful to have all stats/metrics in one nifty struct, so we don't have to fiddle with calling individual methods. We don't need obnoxious API for that thing, other than pub fields and derive(Debug).

Having a private field is only to be future-proof and be able to add more fields w/o breaking people's code.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feel free to move the current stats under that struct and break the API.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe another question: what would be the preferred method and struct name? Stats sounds like it's a statistic, while everything is a constant. Should I prefer Metrics or even CircuitMetrics or something like that?

Beyond multipliers and constraint counts, I don't think there's other metrics to include, right?

Another question: the private PhantomData you refer to, why would the Stats struct need to be generic; do you mean should it reference to the ConstraintSystem, such that an instance of Stats is always correct (by making the CS immutable for the lifetime of the Stats instance)?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, something alongside "metrics" sounds better. I'd prefer to avoid using the term "circuit" since we are not using it anywhere in the API. Maybe simply r1cs::Metrics is good enough?

As of PhantomData: sorry, i meant having a dummy private field with a zero-sized type, so the struct cannot be used in any other way than just reading its fields. E.g. no destructuring etc.

#[derive(Debug)]
struct Metrics {
    pub multipliers_count: usize,
    pub constraints_count: usize,
    _private: ()
}

But it makes Debug printout uglier and you cannot opt out easily. Maybe we should just list the fields w/o any extra precautions.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, I'd leave destructuring open for the user. It may be handy for writing benchmarks, etc; I don't think it leaves a lot open for abuse.

@rubdos
Copy link
Contributor Author

rubdos commented May 19, 2020

Made a r1cs::Metrics struct instead!

Add Metrics struct to count the different kinds of constraints, which comes in
handy when developing and benchmarking larger circuits.

This deprecates and removes the `multipliers_len()` method.
@rubdos
Copy link
Contributor Author

rubdos commented May 19, 2020

Squashed together; didn't make any sense anymore as separate commits. Note that this removes multipliers_len, as suggested by @oleganza .

@oleganza
Copy link
Collaborator

I've added documentation suggestions - please feel free to reword how you please. This patch looks great!

Co-authored-by: Oleg Andreev <oleganza@gmail.com>
@rubdos
Copy link
Contributor Author

rubdos commented May 25, 2020

I hadn't seen your update, I have accepted your suggestions!

@oleganza
Copy link
Collaborator

oleganza commented May 26, 2020

Nightly is already broken for everyone using dalek libraries since Rust renamed asm! macro to llvm_asm!, which breaks subtle (dalek-cryptography/subtle#70), so I'm merging this PR even with CI failing on nightly.

@oleganza oleganza merged commit fdb68ff into dalek-cryptography:develop May 26, 2020
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 this pull request may close these issues.

2 participants