Giter Club home page Giter Club logo

decaf377's Introduction

decaf377

Crates.io

Many zero-knowledge protocols require a cryptographic group that can be used inside of an arithmetic circuit. This is accomplished by defining an “embedded” elliptic curve whose base field is the scalar field of the proving curve used by the proof system.

The Zexe paper, which defined BLS12-377, also defined (but did not name) a cofactor-4 Edwards curve defined over the BLS12-377 scalar field for exactly this purpose. However, non-prime-order groups are a leaky abstraction, forcing all downstream constructions to pay attention to correct handling of the cofactor. Although it is usually possible to do so safely, it requires additional care, and as discussed below, the optimal technique for handling the cofactor is different inside and outside of a circuit.

Instead, applying the Decaf construction to this curve gives decaf377, a clean abstraction that provides a prime-order group, complete with hash-to-group functionality, and works the same way inside and outside of a circuit.

More details are available on the Penumbra website.

Features

  • std: default, for use in std environments,
  • alloc: default, for use in alloc environments,
  • arkworks: default, uses Arkworks crates for elliptic curve operations,
  • u32_backend: uses 32-bit finite field arithmetic (default is 64-bit),
  • r1cs: enables rank-1 constraint system gadgets,
  • parallel: enables the use of parallelism.

Benchmarks

Run criterion benchmarks using:

cargo bench

This will generate a report at target/criterion/report/index.html.

decaf377's People

Contributors

conorsch avatar cronokirby avatar hdevalence avatar neithanmo avatar redshiftzero avatar talderei avatar zbuc avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

decaf377's Issues

Cleanup the crate to avoid duplication

Right now a lot of code is duplicated:

  • Functions in both u32, u64 backends
  • Elligator map and other related logic between arkworks and min_curve backend
    Also, our hacky python script still involves a lot of manual copying, but now we know exactly the constants we need, and can have the script simply generate all of the rust code directly, and have a single constants file.

At some point we should take care of these, on a rainy day with nothing better to do.

r1cs: elligator map

In PR #38, we add an optional r1cs feature that lets us add decaf elements to arkworks r1cs constraint systems, and implement a bunch of gadgets that let us do various operations on these decaf elements in R1CS, i.e. decompress/compress, equality checks between decaf points, and elliptic curve arithmetic.

One followup from #38 is to add support for the elligator map in circuit. We need this for computing the asset-specific generators when checking the integrity of balance commitments.

fix clippy warnings

In the CI config (as in the main penumbra repo) being added in #2 we have clippy commented out, at some point we can resolve those clippy warnings and re-enable the CI check in this repo

r1cs: implementations of `Add` and `AddAssign` differ

Today @zbuc discovered that the implementations of Add and AddAssign differ for ElementVar. Commit 1243d07 has a small reproducer.

The problem here is due to the LazyElementVar we added in #42. The goal of this was to simplify circuit programming: previously we had in several places in the circuits for Penumbra defined the same underlying variable both as an ElementVar and as FqVar (when we wanted the encoding - the element in its compressed form), e.g. we'd have both nk_element and nk_fqvar. The LazyElementVar enabled us to:

  • define a single variable nk that would lazily store either an ElementVar, an FqVar (compressed form), or both,
  • allow the user to call nk.compress() (and nk.decompress()) as many times as is convenient without needing to be concerned about adding constraints for the compression a second time, as the FqVar if it already exists would be returned to the user,

However, in the implementations of the *Assign operations, the inner value on the LazyElementVar was not updated. In this snippet below, self.inner.element() returns a cloned ElementVar, so the original value was not updated:

impl<'a> AddAssign<&'a ElementVar> for ElementVar {
    fn add_assign(&mut self, rhs: &'a ElementVar) {
        self.inner
            .element()
            .expect("element will exist")
            .add_assign(rhs.inner.element().expect("element will exist"));
    }
}

Implement a BLS12-377 curve using the arkworks stack

Right now we have arkworks compatability for the fields, but users would still need to implement the whole BLS12-377 stack themselves by creating appropriate configs. To avoid repeating this, we want a module doing this in this crate.

Migrate related crates into a workspace

We should migrate other crates that depend tightly on decaf377, namely decaf377-rdsa and decaf377-ka into this repository, creating a new workspace.

This would have avoided the need to use git tags recently when shuffling stuff around, and the need to duplicate CI code between the places. These crates will remain tightly coupled for the foreseeable future, so a workspace is sensible.

Add all missing methods, migrate crates to stable release

Right now, several decaf377 dependents like decaf377-rdsa, -ka, etc. were upgraded to recent code changes, but used git tags because of instability related to adding the necessary methods they needed at the last minute.

We should finalize adding these, and then make all of them use a new release we tag.

Fq additional methods without arkworks

In working on #3675 - making poseidon377 work in a no_std environment without a global allocator, i.e. without arkworks - there is some additional functionality needed in this crate on Fq when the arkworks feature is not enabled. This ticket is to track those items as we find them:

  • Fq::pow() - used in poseidon-parameters for the computation of the cofactor matrix here as well as for the computation of the SubWords layer in poseidon-permutation here. This was previously provided via arkwork's ark_ff::Field trait (ref).
  • TK

r1cs: benchmark `AllocVar::new_variable` for `ElementVar`

Followup from #38. When we witness a decaf element, we do some expensive checks in R1CS to certify it is a valid point. This is done in the implementation of AllocVar::new_variable for ElementVar. I think it would be good to add another benchmark to this repository for our awareness benchmarking that function during proof creation. This benchmark should set mode to AllocationMode::Witness.

r1cs: add `EncodingVar` representing a compressed `ElementVar`

After #42 we should add another type in the R1CS feature that represents the encoding of a decaf377 Element in circuit. This type will be called EncodingVar.

Internally, EncodingVar will hold a LazyElementVar created using LazyElementVar::new_from_encoding.

EncodingVar should be public, and used anywhere in the ElementVar API where the encoding is returned or taken as an argument, i.e. compression/decompression.

switch back to arkworks field arithmetic for 64-bit backend

As part of penumbra-zone/penumbra#3526, we added fiat-crypto formally verified field arithmetic implementations to decaf377, moving away from using the Arkworks field arithmetic imlpementation. This unblocked development of Penumbra's ledger app, since the Arkworks field arithmetic allocated.

However, @TalDerei did some very helpful benchmarking here and found that we have a significant performance regression.

This performance regression is blocking migrating downstream crates to the latest stable release (0.9.0, see #93). To move forward without introducing a performance regression we should switch back to Arkworks field arithmetic for the 64-bit backend only. Embedded environments like Ledger development will use the 32-bit backend which will continue to use the formally verified fiat-crypto field arithmetic.

Implement inversion for fiat-generated code

The wrapper types added in #64 don't include inversion. The fiat-generated code has methods that seem to be intended to be used to implement inversion (divstep etc, as seen in cargo doc --open). We'll need to figure out how to use these:

  • Figure out how to wrap the raw fiat methods into our wrapper types. This could either be Fq::inv(&self) -> Option<Fq> (returning None if self == 0) or Fq::inv(&self) -> Fq (returning 0 if self == 0), whichever is convenient to implement.
  • Add property tests that inversion works.
  • Copy wrappers across all six field impls {u32, u64}::{Fp, Fq, Fr}.

Make `Element::basepoint` be a bare function

Currently, the conventional basepoint is created using the Element::basepoint() method. But Element is already designed to be used with the crate prefix as decaf377::Element, so decaf377::Element::basepoint() is a bit unwieldy and redundant.

inverse square root: alpha_5 can be invalid

Reported in Discord:

pcli panicked with the following when I tried to generate a wallet: thread 'main' panicked at 'no entry found for key', /home/.../.cargo/git/checkouts/decaf377-759be7b9e0a7e297/d777a1b/src/invsqrt.rs:151:18

This is an error from when the computed alpha for i=5 (the last iteration) in the Sarkar algorithm is looked up in the s table, so there must be a bug somewhere

Consider redefining decaf377 in terms of a new underlying curve

https://eprint.iacr.org/2021/1152 proposes a new curve defined over the BLS12-381 scalar field called Bandersnatch. This curve has an endomorphism that allows use of the GLV method, making it faster in the software context (outside of a circuit).

Currently, decaf377 is defined in terms of the Edwards-on-BLS12-377 curve created as part of the Zexe paper. But there's no really compelling reason to use that curve in particular — unlike the scenario for ristretto255, there is not a large deployment base already using that curve.

So, instead, it might be better to try to apply the same techniques in the Bandersnatch paper to create a GLV-compatible Edwards curve defined over the BLS12-377 scalar field, and then define decaf377 in terms of that curve.

add support for adding Elements to a circuit

This is a ticket for adding support for decaf377::Element in jf-plonk ark-groth16:

Note: The below is deprecated and applied to when we were going to use plonk but something similar will be done for Groth16

  • Add an optional proofs feature for all the below logic that requires jf-plonk (see: 8689d27)
  • Add an extension trait on PlonkCircuit<Fq>
  • Possibly add a newtype wrapper like EncodingVariable(pub Variable) (to represent an encoded decaf point)
  • Create a ElementVariable wrapper around jf-plonk's PointVariable: this type will only be created by decoding an EncodingVariable or by operating on ElementVariables. This ensures that we are always working with a valid decaf point.
  • Implement encoding and decoding functions (btwn Fq field elements and decaf points)

ci: run sage tests

Not super high priority but someday it would be nice to run the sage files in CI also since we do have tests in there. Currently I'm running the tests whenever I change the file before merging something.

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.