Skip to content

Commit

Permalink
Support new Bulletproof rewind scheme (#50)
Browse files Browse the repository at this point in the history
* Bulletproofs: change message to 20 bytes, allow 2 nonces in generation

* Updated syntax of rewind function

* Update to latest libsecp

* Update tests

* Fix borrow after move

* Update tests
  • Loading branch information
jaspervdm authored and yeastplume committed Jun 10, 2019
1 parent 4e30b31 commit 0b26463
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 31 deletions.
2 changes: 1 addition & 1 deletion src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ pub const PROOF_MSG_SIZE: usize = 2048;
pub const PROOF_MSG_SIZE: usize = 2048;

/// The maximum size of an optional message embedded in a bullet proof
pub const BULLET_PROOF_MSG_SIZE: usize = 16;
pub const BULLET_PROOF_MSG_SIZE: usize = 20;

/// The order of the secp256k1 curve
pub const CURVE_ORDER: [u8; 32] = [
Expand Down
1 change: 0 additions & 1 deletion src/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -589,7 +589,6 @@ extern "C" {

pub fn secp256k1_bulletproof_rangeproof_rewind(
ctx: *const Context,
gens: *const BulletproofGenerators,
value: *mut uint64_t,
blind: *mut c_uchar,
proof: *const c_uchar,
Expand Down
71 changes: 43 additions & 28 deletions src/pedersen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -745,7 +745,8 @@ impl Secp256k1 {
&self,
value: u64,
blind: SecretKey,
nonce: SecretKey,
rewind_nonce: SecretKey,
private_nonce: SecretKey,
extra_data_in: Option<Vec<u8>>,
message: Option<ProofMessage>,
) -> RangeProof {
Expand Down Expand Up @@ -773,12 +774,11 @@ impl Secp256k1 {
None => ptr::null(),
};

// This api is not for multi-party range proof, so all null for these 5 parameters.
// This api is not for multi-party range proof, so all null for these 4 parameters.
let tau_x = ptr::null_mut();
let t_one = ptr::null_mut();
let t_two = ptr::null_mut();
let commits = ptr::null_mut();
let private_nonce = ptr::null();

let _success = unsafe {
let scratch = ffi::secp256k1_scratch_space_create(self.ctx, SCRATCH_SPACE_SIZE);
Expand All @@ -798,8 +798,8 @@ impl Secp256k1 {
1,
constants::GENERATOR_H.as_ptr(),
n_bits as size_t,
nonce.as_ptr(),
private_nonce,
rewind_nonce.as_ptr(),
private_nonce.as_ptr(),
extra_data,
extra_data_len as size_t,
message_ptr,
Expand Down Expand Up @@ -1085,14 +1085,13 @@ impl Secp256k1 {

let mut blind_out = [0u8; constants::SECRET_KEY_SIZE];
let mut value_out = 0;
let mut message_out = [0u8; 16];
let mut message_out = [0u8; 20];
let commit = self.commit_parse(commit.0)?;

let success = unsafe {
let scratch = ffi::secp256k1_scratch_space_create(self.ctx, SCRATCH_SPACE_SIZE);
let result = ffi::secp256k1_bulletproof_rangeproof_rewind(
self.ctx,
shared_generators(self.ctx),
&mut value_out,
blind_out.as_mut_ptr(),
proof.proof.as_ptr(),
Expand Down Expand Up @@ -1393,7 +1392,7 @@ mod tests {
let blinding = SecretKey::new(&secp, &mut thread_rng());
let value = 12345678;
let commit = secp.commit(value, blinding.clone()).unwrap();
let bullet_proof = secp.bullet_proof(value, blinding.clone(), blinding.clone(), None, None);
let bullet_proof = secp.bullet_proof(value, blinding.clone(), blinding.clone(), blinding.clone(), None, None);

// correct verification
println!("Bullet proof len: {}", bullet_proof.plen);
Expand All @@ -1405,7 +1404,7 @@ mod tests {
// wrong value committed to
let value = 12345678;
let wrong_commit = secp.commit(87654321, blinding.clone()).unwrap();
let bullet_proof = secp.bullet_proof(value, blinding.clone(), blinding.clone(), None, None);
let bullet_proof = secp.bullet_proof(value, blinding.clone(), blinding.clone(), blinding.clone(), None, None);
if !secp
.verify_bullet_proof(wrong_commit, bullet_proof, None)
.is_err()
Expand All @@ -1417,7 +1416,7 @@ mod tests {
let value = 12345678;
let commit = secp.commit(value, blinding).unwrap();
let blinding = SecretKey::new(&secp, &mut thread_rng());
let bullet_proof = secp.bullet_proof(value, blinding.clone(), blinding.clone(), None, None);
let bullet_proof = secp.bullet_proof(value, blinding.clone(), blinding.clone(), blinding.clone(), None, None);
if !secp
.verify_bullet_proof(commit, bullet_proof, None)
.is_err()
Expand All @@ -1431,7 +1430,7 @@ mod tests {
let value = 12345678;
let commit = secp.commit(value, blinding.clone()).unwrap();
let bullet_proof =
secp.bullet_proof(value, blinding.clone(), blinding.clone(), Some(extra_data.clone()), None);
secp.bullet_proof(value, blinding.clone(), blinding.clone(), blinding.clone(), Some(extra_data.clone()), None);
if secp
.verify_bullet_proof(commit, bullet_proof, Some(extra_data.clone()))
.is_err()
Expand All @@ -1453,15 +1452,16 @@ mod tests {
// Ensure rewinding works

let blinding = SecretKey::new(&secp, &mut thread_rng());
let nonce = SecretKey::new(&secp, &mut thread_rng());
let rewind_nonce = SecretKey::new(&secp, &mut thread_rng());
let private_nonce = SecretKey::new(&secp, &mut thread_rng());
let value = 12345678;
let commit = secp.commit(value, blinding.clone()).unwrap();

let bullet_proof =
secp.bullet_proof(value, blinding.clone(), nonce.clone(), Some(extra_data.clone()), None);
secp.bullet_proof(value, blinding.clone(), private_nonce.clone(), private_nonce.clone(), Some(extra_data.clone()), None);
// Unwind message with same blinding factor
let proof_info = secp
.rewind_bullet_proof(commit, nonce.clone(), Some(extra_data.clone()), bullet_proof)
.rewind_bullet_proof(commit, private_nonce.clone(), Some(extra_data.clone()), bullet_proof)
.unwrap();
assert_eq!(proof_info.value, value);
assert_eq!(blinding, proof_info.blinding);
Expand All @@ -1478,26 +1478,28 @@ mod tests {
}

// unwinding with wrong extra data should puke
let proof_info = secp.rewind_bullet_proof(commit, nonce.clone(), None, bullet_proof);
let proof_info = secp.rewind_bullet_proof(commit, private_nonce.clone(), None, bullet_proof);
if !proof_info.is_err() {
panic!("Bullet proof verify with message should have errored.");
}

// Ensure including a message also works
let message_bytes: [u8; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
let message_bytes: [u8; 20] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20];
let message = ProofMessage::from_bytes(&message_bytes);

let bullet_proof = secp.bullet_proof(
value,
blinding.clone(),
nonce.clone(),
rewind_nonce.clone(),
private_nonce.clone(),
Some(extra_data.clone()),
Some(message.clone()),
);
// Unwind message with same blinding factor
let proof_info = secp
.rewind_bullet_proof(commit, nonce, Some(extra_data.clone()), bullet_proof)
.rewind_bullet_proof(commit, rewind_nonce, Some(extra_data.clone()), bullet_proof)
.unwrap();
assert_eq!(proof_info.value, value);
assert_eq!(proof_info.message, message);
}

Expand Down Expand Up @@ -1791,7 +1793,7 @@ mod tests {
let commit = secp.commit(value, blinding.clone()).unwrap();

let mut pm = ProofMessage::from_bytes(&[0u8;32]);
let bullet_proof = secp.bullet_proof(value, blinding.clone(), nonce.clone(), None, Some(pm.clone()));
let bullet_proof = secp.bullet_proof(value, blinding.clone(), nonce.clone(), nonce.clone(), None, Some(pm.clone()));
// Unwind message with same blinding factor
let proof_info = secp
.rewind_bullet_proof(commit, nonce, None, bullet_proof)
Expand All @@ -1810,13 +1812,22 @@ mod tests {
let value = <u64>::max_value() - 1;
let commit = secp.commit(value, blinding.clone()).unwrap();

let bullet_proof = secp.bullet_proof(value, blinding.clone(), nonce.clone(), None, None);
let bullet_proof = secp.bullet_proof(value, blinding.clone(), nonce.clone(), nonce.clone(), None, None);
// Unwind message with same blinding factor
let proof_info = secp
.rewind_bullet_proof(commit, nonce, None, bullet_proof)
.rewind_bullet_proof(commit, nonce.clone(), None, bullet_proof)
.unwrap();
assert_eq!(proof_info.value, value);
assert_eq!(blinding, proof_info.blinding);

// Using a different private nonce should prevent rewind of blinding factor
let private_nonce = SecretKey::new(&secp, &mut thread_rng());
let bullet_proof = secp.bullet_proof(value, blinding.clone(), nonce.clone(), private_nonce.clone(), None, None);
let proof_info = secp
.rewind_bullet_proof(commit, nonce, None, bullet_proof)
.unwrap();
assert_eq!(proof_info.value, value);
assert_ne!(blinding, proof_info.blinding);
}

#[ignore]
Expand All @@ -1835,7 +1846,7 @@ mod tests {
let mut proofs: Vec<RangeProof> = vec![];
for i in 0..v {
commits.push(secp.commit(value + i as u64, blinding.clone()).unwrap());
proofs.push(secp.bullet_proof(value + i as u64, blinding.clone(), blinding.clone(), None, None));
proofs.push(secp.bullet_proof(value + i as u64, blinding.clone(), blinding.clone(), blinding.clone(), None, None));
}
println!("--------");
println!("Comparing {} Proofs", v);
Expand Down Expand Up @@ -1866,13 +1877,15 @@ mod tests {

let secp = Secp256k1::with_caps(ContextFlag::Commit);
let blinding = SecretKey::new(&secp, &mut thread_rng());
let rewind_nonce = SecretKey::new(&secp, &mut thread_rng());
let private_nonce = SecretKey::new(&secp, &mut thread_rng());
let wrong_blinding = SecretKey::new(&secp, &mut thread_rng());
let value = 12345678;

let wrong_commit = secp.commit(value, wrong_blinding).unwrap();

commits.push(secp.commit(value, blinding.clone()).unwrap());
proofs.push(secp.bullet_proof(value, blinding.clone(), blinding.clone(), None, None));
proofs.push(secp.bullet_proof(value, blinding.clone(), rewind_nonce.clone(), private_nonce.clone(), None, None));
let proof_range = secp
.verify_bullet_proof(commits[0].clone(), proofs[0].clone(), None)
.unwrap();
Expand All @@ -1898,8 +1911,8 @@ mod tests {
proofs = vec![];
commits.push(secp.commit(value + 1, blinding.clone()).unwrap());
commits.push(secp.commit(value - 1, blinding.clone()).unwrap());
proofs.push(secp.bullet_proof(value + 1, blinding.clone(), blinding.clone(), None, None));
proofs.push(secp.bullet_proof(value - 1, blinding.clone(), blinding.clone(), None, None));
proofs.push(secp.bullet_proof(value + 1, blinding.clone(), rewind_nonce.clone(), private_nonce.clone(), None, None));
proofs.push(secp.bullet_proof(value - 1, blinding.clone(), rewind_nonce.clone(), private_nonce.clone(), None, None));
let proof_range = secp
.verify_bullet_proof_multi(commits.clone(), proofs.clone(), None)
.unwrap();
Expand All @@ -1915,14 +1928,16 @@ mod tests {
proofs.push(secp.bullet_proof(
value + 1,
blinding.clone(),
blinding.clone(),
rewind_nonce.clone(),
private_nonce.clone(),
Some(extra_data1.clone()),
None,
));
proofs.push(secp.bullet_proof(
value - 1,
blinding.clone(),
blinding.clone(),
rewind_nonce.clone(),
private_nonce.clone(),
Some(extra_data2.clone()),
None,
));
Expand Down Expand Up @@ -1954,7 +1969,7 @@ mod tests {
for i in 1..100 {
print!("\r\r\r{}", i);
commits.push(secp.commit(value + i as u64, blinding.clone()).unwrap());
proofs.push(secp.bullet_proof(value + i as u64, blinding.clone(), blinding.clone(), None, None));
proofs.push(secp.bullet_proof(value + i as u64, blinding.clone(), rewind_nonce.clone(), private_nonce.clone(), None, None));
let proof_range = secp.verify_bullet_proof_multi(commits.clone(), proofs.clone(), None); //.unwrap();
if proof_range.is_err() {
println!(" proofs batch verify failed");
Expand Down

0 comments on commit 0b26463

Please sign in to comment.