pub struct RangeProof { /* private fields */ }
Expand description

The RangeProof struct represents a proof that one or more values are in a range.

The RangeProof struct contains functions for creating and verifying aggregated range proofs. The single-value case is implemented as a special case of aggregated range proofs.

The bitsize of the range, as well as the list of commitments to the values, are not included in the proof, and must be known to the verifier.

This implementation requires that both the bitsize n and the aggregation size m be powers of two, so that n = 8, 16, 32, 64 and m = 1, 2, 4, 8, 16, .... Note that the aggregation size is not given as an explicit parameter, but is determined by the number of values or commitments passed to the prover or verifier.

Note

For proving, these functions run the multiparty aggregation protocol locally. That API is exposed in the aggregation module and can be used to perform online aggregation between parties without revealing secret values to each other.

Implementations§

source§

impl RangeProof

source

pub fn prove_single_with_rng<T: RngCore + CryptoRng>( bp_gens: &BulletproofGens, pc_gens: &PedersenGens, transcript: &mut Transcript, v: u64, v_blinding: &Scalar, n: usize, rng: &mut T ) -> Result<(RangeProof, CompressedRistretto), ProofError>

Create a rangeproof for a given pair of value v and blinding scalar v_blinding. This is a convenience wrapper around RangeProof::prove_multiple.

Example
extern crate rand;
use rand::thread_rng;

extern crate curve25519_dalek;
use curve25519_dalek::scalar::Scalar;

extern crate merlin;
use merlin::Transcript;

extern crate tari_bulletproofs;
use tari_bulletproofs::{BulletproofGens, PedersenGens, RangeProof};

// Generators for Pedersen commitments.  These can be selected
// independently of the Bulletproofs generators.
let pc_gens = PedersenGens::default();

// Generators for Bulletproofs, valid for proofs up to bitsize 64
// and aggregation size up to 1.
let bp_gens = BulletproofGens::new(64, 1);

// A secret value we want to prove lies in the range [0, 2^32)
let secret_value = 1037578891u64;

// The API takes a blinding factor for the commitment.
let blinding = Scalar::random(&mut thread_rng());

// The proof can be chained to an existing transcript.
// Here we create a transcript with a doctest domain separator.
let mut prover_transcript = Transcript::new(b"doctest example");

// Create a 32-bit rangeproof.
let (proof, committed_value) = RangeProof::prove_single(
    &bp_gens,
    &pc_gens,
    &mut prover_transcript,
    secret_value,
    &blinding,
    32,
).expect("A real program could handle errors");

// Verification requires a transcript with identical initial state:
let mut verifier_transcript = Transcript::new(b"doctest example");
assert!(
    proof
        .verify_single(&bp_gens, &pc_gens, &mut verifier_transcript, &committed_value, 32)
        .is_ok()
);
source

pub fn prove_single_with_rng_and_rewind_key<T: RngCore + CryptoRng>( bp_gens: &BulletproofGens, pc_gens: &PedersenGens, transcript: &mut Transcript, v: u64, v_blinding: &Scalar, n: usize, rng: &mut T, pvt_rewind_key: &Scalar, pvt_blinding_key: &Scalar, proof_message: &[u8; 23] ) -> Result<(RangeProof, CompressedRistretto), ProofError>

Create a rangeproof for a given pair of value v and blinding scalar v_blinding, passing in a rewind key to enable rangeproof rewinding with 23 bytes worth of extra data that can be embedded. This is a convenience wrapper around RangeProof::prove_multiple.

Example
extern crate rand;
use rand::thread_rng;

extern crate curve25519_dalek;
use curve25519_dalek::scalar::Scalar;

extern crate merlin;
use merlin::Transcript;

extern crate tari_bulletproofs;
use tari_bulletproofs::{BulletproofGens, PedersenGens, RangeProof};

// Generators for Pedersen commitments.  These can be selected
// independently of the Bulletproofs generators.
use curve25519_dalek::ristretto::RistrettoPoint;
use curve25519_dalek::constants::RISTRETTO_BASEPOINT_TABLE;
use tari_bulletproofs::range_proof::{get_rewind_nonce_from_pub_key, get_secret_nonce_from_pvt_key};
let pc_gens = PedersenGens::default();

// Generators for Bulletproofs, valid for proofs up to bitsize 64
// and aggregation size up to 1.
let bp_gens = BulletproofGens::new(64, 1);

// A secret value we want to prove lies in the range [0, 2^32)
let confidential_value = 1037578891u64;

// The API takes a blinding factor for the commitment.
let blinding_factor = Scalar::random(&mut thread_rng());

// The private keys for range proof rewinding; these may be based on a wallet's private root key
let pvt_rewind_key = Scalar::random(&mut thread_rng());
let pvt_blinding_key = Scalar::random(&mut thread_rng());

// Up to 23 bytes extra data may be embedded in the range proof meta data
let proof_message: [u8; 23] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
        18, 19, 20, 21, 22, 23];

// The proof can be chained to an existing transcript.
// Here we create a transcript with a doctest domain separator.
let mut prover_transcript = Transcript::new(b"doctest example");

// Create a 32-bit rangeproof.
let (proof, committed_value) = RangeProof::prove_single_with_rewind_key(
    &bp_gens,
    &pc_gens,
    &mut prover_transcript,
    confidential_value,
    &blinding_factor,
    32,
    &pvt_rewind_key,
    &pvt_blinding_key,
    &proof_message,
).expect("A real program could handle errors");

// Verification requires a transcript with identical initial state:
let mut verifier_transcript = Transcript::new(b"doctest example");
assert!(
    proof
        .verify_single(&bp_gens, &pc_gens, &mut verifier_transcript, &committed_value, 32)
        .is_ok()
);

// A third party may have access to the public keys and extra data for range proof rewinding
let pub_rewind_key_1 = RistrettoPoint::from(&pvt_rewind_key * &RISTRETTO_BASEPOINT_TABLE).compress();
let pub_rewind_key_2 = RistrettoPoint::from(&pvt_blinding_key * &RISTRETTO_BASEPOINT_TABLE).compress();

// The rewind nonce is necessary to rewind the range proof, which is uniquely bound to the commitment
let rewind_nonce_1 = get_rewind_nonce_from_pub_key(&pub_rewind_key_1, &committed_value);
let rewind_nonce_2 = get_rewind_nonce_from_pub_key(&pub_rewind_key_2, &committed_value);

// A owner or third party can extract the value and extra data; if it is the wrong combination
// garbage data will be extracted
let mut rewind_transcript = Transcript::new(b"doctest example");
assert_eq!(
    proof.rewind_single_get_value_only(
        &bp_gens,
        &mut rewind_transcript,
        &committed_value,
        32,
        &rewind_nonce_1,
        &rewind_nonce_2,
    ),
    Ok((confidential_value, proof_message))
);

// The two blinding nonces are necessary to rewind the range proof fully, which are also
// uniquely bound to the commitment
let blinding_nonce_1 = get_secret_nonce_from_pvt_key(&pvt_rewind_key, &committed_value);
let blinding_nonce_2 = get_secret_nonce_from_pvt_key(&pvt_blinding_key, &committed_value);

// The owner or trusted party can extract the value, extra data and blinding factor; if it is the
// wrong combination an error will be returned
let mut rewind_transcript = Transcript::new(b"doctest example");
assert_eq!(
    proof.rewind_single_get_commitment_data(
        &bp_gens,
        &pc_gens,
        &mut rewind_transcript,
        &committed_value,
        32,
        &rewind_nonce_1,
        &rewind_nonce_2,
        &blinding_nonce_1,
        &blinding_nonce_2,
    ),
    Ok((confidential_value, blinding_factor, proof_message))
);
source

pub fn prove_single( bp_gens: &BulletproofGens, pc_gens: &PedersenGens, transcript: &mut Transcript, v: u64, v_blinding: &Scalar, n: usize ) -> Result<(RangeProof, CompressedRistretto), ProofError>

Create a rangeproof for a given pair of value v and blinding scalar v_blinding. This is a convenience wrapper around RangeProof::prove_single_with_rng, passing in a threadsafe RNG.

source

pub fn prove_single_with_rewind_key( bp_gens: &BulletproofGens, pc_gens: &PedersenGens, transcript: &mut Transcript, v: u64, v_blinding: &Scalar, n: usize, pvt_rewind_key: &Scalar, pvt_blinding_key: &Scalar, proof_message: &[u8; 23] ) -> Result<(RangeProof, CompressedRistretto), ProofError>

Create a rangeproof for a given pair of value v and blinding scalar v_blinding, passing in a rewind key to enable rangeproof rewinding with 23 bytes worth of extra data that can be embedded. This is a convenience wrapper around RangeProof::prove_single_with_rng_and_rewind_key, passing in a threadsafe RNG.

source

pub fn prove_multiple_with_rng<T: RngCore + CryptoRng>( bp_gens: &BulletproofGens, pc_gens: &PedersenGens, transcript: &mut Transcript, values: &[u64], blindings: &[Scalar], n: usize, rng: &mut T ) -> Result<(RangeProof, Vec<CompressedRistretto>), ProofError>

Create a rangeproof for a set of values.

Example
extern crate rand;
use rand::thread_rng;

extern crate curve25519_dalek;
use curve25519_dalek::scalar::Scalar;

extern crate merlin;
use merlin::Transcript;

extern crate tari_bulletproofs;
use tari_bulletproofs::{BulletproofGens, PedersenGens, RangeProof};

// Generators for Pedersen commitments.  These can be selected
// independently of the Bulletproofs generators.
let pc_gens = PedersenGens::default();

// Generators for Bulletproofs, valid for proofs up to bitsize 64
// and aggregation size up to 16.
let bp_gens = BulletproofGens::new(64, 16);

// Four secret values we want to prove lie in the range [0, 2^32)
let secrets = [4242344947u64, 3718732727u64, 2255562556u64, 2526146994u64];

// The API takes blinding factors for the commitments.
let blindings: Vec<_> = (0..4).map(|_| Scalar::random(&mut thread_rng())).collect();

// The proof can be chained to an existing transcript.
// Here we create a transcript with a doctest domain separator.
let mut prover_transcript = Transcript::new(b"doctest example");

// Create an aggregated 32-bit rangeproof and corresponding commitments.
let (proof, commitments) = RangeProof::prove_multiple(
    &bp_gens,
    &pc_gens,
    &mut prover_transcript,
    &secrets,
    &blindings,
    32,
).expect("A real program could handle errors");

// Verification requires a transcript with identical initial state:
let mut verifier_transcript = Transcript::new(b"doctest example");
assert!(
    proof
        .verify_multiple(&bp_gens, &pc_gens, &mut verifier_transcript, &commitments, 32)
        .is_ok()
);
source

pub fn prove_multiple( bp_gens: &BulletproofGens, pc_gens: &PedersenGens, transcript: &mut Transcript, values: &[u64], blindings: &[Scalar], n: usize ) -> Result<(RangeProof, Vec<CompressedRistretto>), ProofError>

Create a rangeproof for a set of values. This is a convenience wrapper around RangeProof::prove_multiple_with_rng, passing in a threadsafe RNG.

source

pub fn verify_single_with_rng<T: RngCore + CryptoRng>( &self, bp_gens: &BulletproofGens, pc_gens: &PedersenGens, transcript: &mut Transcript, V: &CompressedRistretto, n: usize, rng: &mut T ) -> Result<(), ProofError>

Verifies a rangeproof for a given value commitment \(V\).

This is a convenience wrapper around verify_multiple for the m=1 case.

source

pub fn verify_single( &self, bp_gens: &BulletproofGens, pc_gens: &PedersenGens, transcript: &mut Transcript, V: &CompressedRistretto, n: usize ) -> Result<(), ProofError>

Verifies a rangeproof for a given value commitment \(V\).

This is a convenience wrapper around RangeProof::verify_single_with_rng, passing in a threadsafe RNG.

source

pub fn verify_multiple_with_rng<T: RngCore + CryptoRng>( &self, bp_gens: &BulletproofGens, pc_gens: &PedersenGens, transcript: &mut Transcript, value_commitments: &[CompressedRistretto], n: usize, rng: &mut T ) -> Result<(), ProofError>

Verifies an aggregated rangeproof for the given value commitments.

source

pub fn verify_multiple( &self, bp_gens: &BulletproofGens, pc_gens: &PedersenGens, transcript: &mut Transcript, value_commitments: &[CompressedRistretto], n: usize ) -> Result<(), ProofError>

Verifies an aggregated rangeproof for the given value commitments. This is a convenience wrapper around RangeProof::verify_multiple_with_rng, passing in a threadsafe RNG.

source

pub fn to_bytes(&self) -> Vec<u8>

Serializes the proof into a byte array of \(2 \lg n + 9\) 32-byte elements, where \(n\) is the number of secret bits.

Layout

The layout of the range proof encoding is:

  • four compressed Ristretto points \(A,S,T_1,T_2\),
  • three scalars \(t_x, \tilde{t}_x, \tilde{e}\),
  • \(n\) pairs of compressed Ristretto points \(L_0,R_0\dots,L_{n-1},R_{n-1}\),
  • two scalars \(a, b\).
source

pub fn from_bytes(slice: &[u8]) -> Result<RangeProof, ProofError>

Deserializes the proof from a byte slice.

Returns an error if the byte slice cannot be parsed into a RangeProof.

source

pub fn rewind_single_get_commitment_data( &self, bp_gens: &BulletproofGens, pc_gens: &PedersenGens, transcript: &mut Transcript, value_commitment: &CompressedRistretto, n: usize, rewind_nonce_1: &Scalar, rewind_nonce_2: &Scalar, blinding_nonce_1: &Scalar, blinding_nonce_2: &Scalar ) -> Result<(u64, Scalar, [u8; 23]), ProofError>

Rewinds a rangeproof for a given value commitment \(V\), returning the value, blinding factor and 23 bytes extra data upon success.

source

pub fn rewind_single_get_value_only( &self, bp_gens: &BulletproofGens, transcript: &mut Transcript, V: &CompressedRistretto, n: usize, rewind_nonce_1: &Scalar, rewind_nonce_2: &Scalar ) -> Result<(u64, [u8; 23]), ProofError>

Rewinds a rangeproof for a given value commitment \(V\) to get the value and 23 bytes extra data only. If the wrong rewind_nonce is provided, garbage data will be returned.

Trait Implementations§

source§

impl Clone for RangeProof

source§

fn clone(&self) -> RangeProof

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for RangeProof

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'de> Deserialize<'de> for RangeProof

source§

fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>where D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl Serialize for RangeProof

source§

fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>where S: Serializer,

Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

const: unstable · source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

const: unstable · source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

const: unstable · source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for Twhere U: From<T>,

const: unstable · source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> Same<T> for T

§

type Output = T

Should always be Self
source§

impl<T> ToOwned for Twhere T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
const: unstable · source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
const: unstable · source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for Twhere V: MultiLane<T>,

§

fn vzip(self) -> V

source§

impl<T> DeserializeOwned for Twhere T: for<'de> Deserialize<'de>,