# Crate dalek_rangeproofs [−] [src]

A pure-Rust implementation of the Back-Maxwell rangeproof scheme defined in Confidential Assets (2017) by Poelstra, Back, Friedenbach, Maxwell, Wuille.

The scheme is instantiated using the Decaf group on Curve25519, as implemented in `curve25519-dalek`. Note that since the Decaf implementation in `curve25519-dalek` is currently UNFINISHED, UNREVIEWED, AND EXPERIMENTAL, so is this library.

This implementation hardcodes the ring size `m = 3`, as this is the most efficient choice. The number of rings `n` determines the range `[0,3^n]`, as well as the size and speed of the proof.

# Examples

Suppose we want to prove that `134492616741` is within `[0,3^40]`. Since 340 ≅ 0.66 (264 ), this is just slightly narrower than the range of a `u64`.

To construct a proof that `134492616741` is within `[0,3^40]`, first choose orthogonal basepoints. Usually the basepoints would be set or distributed as system-wide parameters. Here we choose `G` to be the Decaf coset containing the ed25519 basepoint and generate the second basepoint as `H = Hash(G)`. (Technically, `G` is actually a `DecafBasepointTable`, which implements `Mul<&Scalar>` using a precomputed table).

```use sha2::Sha256;

use curve25519_dalek::constants as dalek_constants;
use curve25519_dalek::decaf::{DecafBasepointTable, DecafPoint};
use curve25519_dalek::scalar::Scalar;

let G = &dalek_constants::DECAF_ED25519_BASEPOINT_TABLE;
let H = DecafPoint::hash_from_bytes::<Sha256>(G.basepoint().compress().as_bytes());
```

You'll also need your value and a CSPRNG:

```use rand::OsRng;

let mut csprng = OsRng::new().unwrap();
let value = 134492616741;```

We can now create the rangeproof, like so:

```use dalek_rangeproofs::RangeProof;

let (proof, commitment, blinding) =
RangeProof::create(40, value, G, &H, &mut csprng).unwrap();```

The output is the proof `proof`, as well as `commitment = blinding*G + value*H`.

We can serialize the proof using Serde. Here, we use CBOR.

```extern crate serde_cbor;

let proof_bytes: Vec<u8> = serde_cbor::ser::to_vec_packed(&proof).unwrap();
assert_eq!(proof_bytes.len(), 4125);```

In this case, the `serde_cbor`-encoded proof statement is approximately 6.5% larger than the optimal 3872 = 32(1+3*40) bytes. Another party can verify the proof statement from `proof_bytes` by doing:

```extern crate serde_cbor;
use dalek_rangeproofs::RangeProof;
let proof: RangeProof = serde_cbor::from_slice(&proof_bytes).unwrap();

let C_option = proof.verify(40, G, &H);
assert!(C_option.is_some());

let C = C_option.unwrap();```

If the proof is well-formed, `verify` returns the commitment to the value. Since the commitment is the output of the verification, the verifier is assured it opens to a value in the range `[0,3^n]`. However, without knowing both `blinding` and the actual `value`, the verifier cannot open this commitment, because Pedersen commitments are computationally binding and perfectly hiding (in addition to being additively homomorphic, a feature used within this scheme).

Later, to open this commitment, the prover could reveal the value and the blinding, allowing others to check that `commitment = blinding*G + value*H`.

```let C_hat = &(G * &blinding) + &(&H * &Scalar::from_u64(value));

assert_eq!(C_hat, C);```

## Structs

 RangeProof A Back-Maxwell rangeproof, which proves in zero knowledge that a number is in a range `[0,m^n]`. We hardcode `m = 3` as this is the most efficient.

## Constants

 RANGEPROOF_MAX_N The maximum allowed bound for the rangeproof. Currently this is set to 41, because we only implement conversion to base 3 digits for `u64`s, and 341 is the least power of 3 greater than `2^64`.