-
Notifications
You must be signed in to change notification settings - Fork 219
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
bulletproofs: add closure to allow increases to prover generator capacity #266
Open
vickiniu
wants to merge
4
commits into
dalek-cryptography:develop
Choose a base branch
from
vickiniu:vicki/capacity-closure
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 2 commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -65,7 +65,7 @@ impl ShuffleProof { | |
/// Returns a tuple `(proof, input_commitments || output_commitments)`. | ||
pub fn prove<'a, 'b>( | ||
pc_gens: &'b PedersenGens, | ||
bp_gens: &'b BulletproofGens, | ||
bp_gens: &'b mut BulletproofGens, | ||
transcript: &'a mut Transcript, | ||
input: &[Scalar], | ||
output: &[Scalar], | ||
|
@@ -100,7 +100,9 @@ impl ShuffleProof { | |
|
||
ShuffleProof::gadget(&mut prover, input_vars, output_vars)?; | ||
|
||
let proof = prover.prove(&bp_gens)?; | ||
let proof = prover.prove(bp_gens, |capacity, gens| { | ||
gens.increase_capacity(capacity); | ||
})?; | ||
|
||
Ok((ShuffleProof(proof), input_commitments, output_commitments)) | ||
} | ||
|
@@ -144,7 +146,7 @@ fn kshuffle_helper(k: usize) { | |
|
||
// Common code | ||
let pc_gens = PedersenGens::default(); | ||
let bp_gens = BulletproofGens::new((2 * k).next_power_of_two(), 1); | ||
let mut bp_gens = BulletproofGens::new((2 * k).next_power_of_two(), 1); | ||
|
||
let (proof, input_commitments, output_commitments) = { | ||
// Randomly generate inputs and outputs to kshuffle | ||
|
@@ -157,7 +159,14 @@ fn kshuffle_helper(k: usize) { | |
rand::thread_rng().shuffle(&mut output); | ||
|
||
let mut prover_transcript = Transcript::new(b"ShuffleProofTest"); | ||
ShuffleProof::prove(&pc_gens, &bp_gens, &mut prover_transcript, &input, &output).unwrap() | ||
ShuffleProof::prove( | ||
&pc_gens, | ||
&mut bp_gens, | ||
&mut prover_transcript, | ||
&input, | ||
&output, | ||
) | ||
.unwrap() | ||
}; | ||
|
||
{ | ||
|
@@ -236,7 +245,7 @@ fn example_gadget<CS: ConstraintSystem>( | |
// Prover's scope | ||
fn example_gadget_proof( | ||
pc_gens: &PedersenGens, | ||
bp_gens: &BulletproofGens, | ||
bp_gens: &mut BulletproofGens, | ||
a1: u64, | ||
a2: u64, | ||
b1: u64, | ||
|
@@ -267,7 +276,9 @@ fn example_gadget_proof( | |
); | ||
|
||
// 4. Make a proof | ||
let proof = prover.prove(bp_gens)?; | ||
let proof = prover.prove(bp_gens, |capacity, gens| { | ||
gens.increase_capacity(capacity); | ||
})?; | ||
|
||
Ok((proof, commitments)) | ||
} | ||
|
@@ -315,9 +326,10 @@ fn example_gadget_roundtrip_helper( | |
) -> Result<(), R1CSError> { | ||
// Common | ||
let pc_gens = PedersenGens::default(); | ||
let bp_gens = BulletproofGens::new(128, 1); | ||
let mut bp_gens = BulletproofGens::new(128, 1); | ||
|
||
let (proof, commitments) = example_gadget_proof(&pc_gens, &bp_gens, a1, a2, b1, b2, c1, c2)?; | ||
let (proof, commitments) = | ||
example_gadget_proof(&pc_gens, &mut bp_gens, a1, a2, b1, b2, c1, c2)?; | ||
|
||
example_gadget_verify(&pc_gens, &bp_gens, c2, proof, commitments) | ||
} | ||
|
@@ -332,9 +344,10 @@ fn example_gadget_roundtrip_serialization_helper( | |
) -> Result<(), R1CSError> { | ||
// Common | ||
let pc_gens = PedersenGens::default(); | ||
let bp_gens = BulletproofGens::new(128, 1); | ||
let mut bp_gens = BulletproofGens::new(128, 1); | ||
|
||
let (proof, commitments) = example_gadget_proof(&pc_gens, &bp_gens, a1, a2, b1, b2, c1, c2)?; | ||
let (proof, commitments) = | ||
example_gadget_proof(&pc_gens, &mut bp_gens, a1, a2, b1, b2, c1, c2)?; | ||
|
||
let proof = proof.to_bytes(); | ||
|
||
|
@@ -417,7 +430,7 @@ fn range_proof_gadget() { | |
fn range_proof_helper(v_val: u64, n: usize) -> Result<(), R1CSError> { | ||
// Common | ||
let pc_gens = PedersenGens::default(); | ||
let bp_gens = BulletproofGens::new(128, 1); | ||
let mut bp_gens = BulletproofGens::new(128, 1); | ||
|
||
// Prover's scope | ||
let (proof, commitment) = { | ||
|
@@ -430,8 +443,7 @@ fn range_proof_helper(v_val: u64, n: usize) -> Result<(), R1CSError> { | |
let (com, var) = prover.commit(v_val.into(), Scalar::random(&mut rng)); | ||
assert!(range_proof(&mut prover, var.into(), Some(v_val), n).is_ok()); | ||
|
||
let proof = prover.prove(&bp_gens)?; | ||
|
||
let proof = prover.prove(&mut bp_gens, |capacity, gens| ())?; | ||
(proof, com) | ||
}; | ||
|
||
|
@@ -447,3 +459,56 @@ fn range_proof_helper(v_val: u64, n: usize) -> Result<(), R1CSError> { | |
// Verifier verifies proof | ||
Ok(verifier.verify(&proof, &pc_gens, &bp_gens)?) | ||
} | ||
|
||
fn prover_capacity_resize_helper<F>( | ||
capacity: usize, | ||
resize_fn: F, | ||
) -> Result<(R1CSProof, CompressedRistretto), R1CSError> | ||
where | ||
F: FnMut(usize, &mut BulletproofGens), | ||
{ | ||
// Common | ||
let pc_gens = PedersenGens::default(); | ||
let mut bp_gens = BulletproofGens::new(capacity, 1); | ||
|
||
// Prover makes a `ConstraintSystem` instance representing a range proof gadget | ||
let mut prover_transcript = Transcript::new(b"RangeProofTest"); | ||
let mut rng = rand::thread_rng(); | ||
|
||
let mut prover = Prover::new(&pc_gens, &mut prover_transcript); | ||
|
||
let (com, var) = prover.commit(10u64.into(), Scalar::random(&mut rng)); | ||
assert!(range_proof(&mut prover, var.into(), Some(10u64), 32).is_ok()); | ||
|
||
let proof = prover.prove(&mut bp_gens, resize_fn)?; | ||
Ok((proof, com)) | ||
} | ||
|
||
#[test] | ||
fn prover_capacity_resize() { | ||
assert!(prover_capacity_resize_helper(128, |_, _| ()).is_ok()); | ||
assert!(prover_capacity_resize_helper(0, |_, _| ()).is_err()); | ||
assert!( | ||
prover_capacity_resize_helper(0, |capacity, gens| gens.increase_capacity(capacity)).is_ok() | ||
); | ||
|
||
let (proof, com) = | ||
prover_capacity_resize_helper(64, |capacity, gens| gens.increase_capacity(capacity)) | ||
.unwrap(); | ||
|
||
// Construct verifier generators | ||
let pc_gens = PedersenGens::default(); | ||
let mut bp_gens = BulletproofGens::new(128, 1); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should there be an interface for the verifier to get the needed capacity for a proof (an added field in R1CSProof)? |
||
|
||
// Verifier makes a `ConstraintSystem` instance representing a merge gadget | ||
let mut verifier_transcript = Transcript::new(b"RangeProofTest"); | ||
let mut verifier = Verifier::new(&mut verifier_transcript); | ||
|
||
let var = verifier.commit(com); | ||
|
||
// Verifier adds constraints to the constraint system | ||
assert!(range_proof(&mut verifier, var.into(), None, 32).is_ok()); | ||
|
||
// Verifier verifies proof | ||
assert!(verifier.verify(&proof, &pc_gens, &bp_gens).is_ok()); | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe instead of sending generators into
prove
, and then getting them into closure, instead simply provide the reference from the closure (not sure if borrowck would love this):?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And the closure must return
Result<&BulletproofGens, R1CSError>
because the prover may decide to return Err if capacity is too high instead of blinding increasing it.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Having the closure provide the reference makes the borrow checker unhappy 😢 says it can't infer the appropriate lifetime?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The prover can provide a closure that doesn't resize the generators (which would result in a failure from insufficient capacity). Do we want to also have the closure return
Result<(), R1CSError>
? It feels maybe unnecessary to me since a no-op closure will have the same overall effect